xref: /freebsd/contrib/libevent/test/regress_buffer.c (revision c43e99fd14c915adcb7173dd49c31e803ceadfe0)
1*c43e99fdSEd Maste /*
2*c43e99fdSEd Maste  * Copyright (c) 2003-2007 Niels Provos <provos@citi.umich.edu>
3*c43e99fdSEd Maste  * Copyright (c) 2007-2012 Niels Provos and Nick Mathewson
4*c43e99fdSEd Maste  *
5*c43e99fdSEd Maste  * Redistribution and use in source and binary forms, with or without
6*c43e99fdSEd Maste  * modification, are permitted provided that the following conditions
7*c43e99fdSEd Maste  * are met:
8*c43e99fdSEd Maste  * 1. Redistributions of source code must retain the above copyright
9*c43e99fdSEd Maste  *    notice, this list of conditions and the following disclaimer.
10*c43e99fdSEd Maste  * 2. Redistributions in binary form must reproduce the above copyright
11*c43e99fdSEd Maste  *    notice, this list of conditions and the following disclaimer in the
12*c43e99fdSEd Maste  *    documentation and/or other materials provided with the distribution.
13*c43e99fdSEd Maste  * 3. The name of the author may not be used to endorse or promote products
14*c43e99fdSEd Maste  *    derived from this software without specific prior written permission.
15*c43e99fdSEd Maste  *
16*c43e99fdSEd Maste  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
17*c43e99fdSEd Maste  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
18*c43e99fdSEd Maste  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
19*c43e99fdSEd Maste  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
20*c43e99fdSEd Maste  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
21*c43e99fdSEd Maste  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
22*c43e99fdSEd Maste  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
23*c43e99fdSEd Maste  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24*c43e99fdSEd Maste  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
25*c43e99fdSEd Maste  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26*c43e99fdSEd Maste  */
27*c43e99fdSEd Maste #include "util-internal.h"
28*c43e99fdSEd Maste 
29*c43e99fdSEd Maste #ifdef _WIN32
30*c43e99fdSEd Maste #include <winsock2.h>
31*c43e99fdSEd Maste #include <windows.h>
32*c43e99fdSEd Maste #endif
33*c43e99fdSEd Maste 
34*c43e99fdSEd Maste #include "event2/event-config.h"
35*c43e99fdSEd Maste 
36*c43e99fdSEd Maste #include <sys/types.h>
37*c43e99fdSEd Maste #include <sys/stat.h>
38*c43e99fdSEd Maste #ifdef EVENT__HAVE_SYS_TIME_H
39*c43e99fdSEd Maste #include <sys/time.h>
40*c43e99fdSEd Maste #endif
41*c43e99fdSEd Maste #include <sys/queue.h>
42*c43e99fdSEd Maste #ifndef _WIN32
43*c43e99fdSEd Maste #include <sys/socket.h>
44*c43e99fdSEd Maste #include <sys/wait.h>
45*c43e99fdSEd Maste #include <signal.h>
46*c43e99fdSEd Maste #include <unistd.h>
47*c43e99fdSEd Maste #include <netdb.h>
48*c43e99fdSEd Maste #endif
49*c43e99fdSEd Maste #include <stdlib.h>
50*c43e99fdSEd Maste #include <stdio.h>
51*c43e99fdSEd Maste #include <string.h>
52*c43e99fdSEd Maste #include <errno.h>
53*c43e99fdSEd Maste #include <assert.h>
54*c43e99fdSEd Maste 
55*c43e99fdSEd Maste #include "event2/event.h"
56*c43e99fdSEd Maste #include "event2/buffer.h"
57*c43e99fdSEd Maste #include "event2/buffer_compat.h"
58*c43e99fdSEd Maste #include "event2/util.h"
59*c43e99fdSEd Maste 
60*c43e99fdSEd Maste #include "defer-internal.h"
61*c43e99fdSEd Maste #include "evbuffer-internal.h"
62*c43e99fdSEd Maste #include "log-internal.h"
63*c43e99fdSEd Maste 
64*c43e99fdSEd Maste #include "regress.h"
65*c43e99fdSEd Maste 
66*c43e99fdSEd Maste /* Validates that an evbuffer is good. Returns false if it isn't, true if it
67*c43e99fdSEd Maste  * is*/
68*c43e99fdSEd Maste static int
69*c43e99fdSEd Maste evbuffer_validate_(struct evbuffer *buf)
70*c43e99fdSEd Maste {
71*c43e99fdSEd Maste 	struct evbuffer_chain *chain;
72*c43e99fdSEd Maste 	size_t sum = 0;
73*c43e99fdSEd Maste 	int found_last_with_datap = 0;
74*c43e99fdSEd Maste 
75*c43e99fdSEd Maste 	if (buf->first == NULL) {
76*c43e99fdSEd Maste 		tt_assert(buf->last == NULL);
77*c43e99fdSEd Maste 		tt_assert(buf->total_len == 0);
78*c43e99fdSEd Maste 	}
79*c43e99fdSEd Maste 
80*c43e99fdSEd Maste 	chain = buf->first;
81*c43e99fdSEd Maste 
82*c43e99fdSEd Maste 	tt_assert(buf->last_with_datap);
83*c43e99fdSEd Maste 	if (buf->last_with_datap == &buf->first)
84*c43e99fdSEd Maste 		found_last_with_datap = 1;
85*c43e99fdSEd Maste 
86*c43e99fdSEd Maste 	while (chain != NULL) {
87*c43e99fdSEd Maste 		if (&chain->next == buf->last_with_datap)
88*c43e99fdSEd Maste 			found_last_with_datap = 1;
89*c43e99fdSEd Maste 		sum += chain->off;
90*c43e99fdSEd Maste 		if (chain->next == NULL) {
91*c43e99fdSEd Maste 			tt_assert(buf->last == chain);
92*c43e99fdSEd Maste 		}
93*c43e99fdSEd Maste 		tt_assert(chain->buffer_len >= chain->misalign + chain->off);
94*c43e99fdSEd Maste 		chain = chain->next;
95*c43e99fdSEd Maste 	}
96*c43e99fdSEd Maste 
97*c43e99fdSEd Maste 	if (buf->first)
98*c43e99fdSEd Maste 		tt_assert(*buf->last_with_datap);
99*c43e99fdSEd Maste 
100*c43e99fdSEd Maste 	if (*buf->last_with_datap) {
101*c43e99fdSEd Maste 		chain = *buf->last_with_datap;
102*c43e99fdSEd Maste 		if (chain->off == 0 || buf->total_len == 0) {
103*c43e99fdSEd Maste 			tt_assert(chain->off == 0)
104*c43e99fdSEd Maste 			tt_assert(chain == buf->first);
105*c43e99fdSEd Maste 			tt_assert(buf->total_len == 0);
106*c43e99fdSEd Maste 		}
107*c43e99fdSEd Maste 		chain = chain->next;
108*c43e99fdSEd Maste 		while (chain != NULL) {
109*c43e99fdSEd Maste 			tt_assert(chain->off == 0);
110*c43e99fdSEd Maste 			chain = chain->next;
111*c43e99fdSEd Maste 		}
112*c43e99fdSEd Maste 	} else {
113*c43e99fdSEd Maste 		tt_assert(buf->last_with_datap == &buf->first);
114*c43e99fdSEd Maste 	}
115*c43e99fdSEd Maste 	tt_assert(found_last_with_datap);
116*c43e99fdSEd Maste 
117*c43e99fdSEd Maste 	tt_assert(sum == buf->total_len);
118*c43e99fdSEd Maste 	return 1;
119*c43e99fdSEd Maste  end:
120*c43e99fdSEd Maste 	return 0;
121*c43e99fdSEd Maste }
122*c43e99fdSEd Maste 
123*c43e99fdSEd Maste static void
124*c43e99fdSEd Maste evbuffer_get_waste(struct evbuffer *buf, size_t *allocatedp, size_t *wastedp, size_t *usedp)
125*c43e99fdSEd Maste {
126*c43e99fdSEd Maste 	struct evbuffer_chain *chain;
127*c43e99fdSEd Maste 	size_t a, w, u;
128*c43e99fdSEd Maste 	int n = 0;
129*c43e99fdSEd Maste 	u = a = w = 0;
130*c43e99fdSEd Maste 
131*c43e99fdSEd Maste 	chain = buf->first;
132*c43e99fdSEd Maste 	/* skip empty at start */
133*c43e99fdSEd Maste 	while (chain && chain->off==0) {
134*c43e99fdSEd Maste 		++n;
135*c43e99fdSEd Maste 		a += chain->buffer_len;
136*c43e99fdSEd Maste 		chain = chain->next;
137*c43e99fdSEd Maste 	}
138*c43e99fdSEd Maste 	/* first nonempty chain: stuff at the end only is wasted. */
139*c43e99fdSEd Maste 	if (chain) {
140*c43e99fdSEd Maste 		++n;
141*c43e99fdSEd Maste 		a += chain->buffer_len;
142*c43e99fdSEd Maste 		u += chain->off;
143*c43e99fdSEd Maste 		if (chain->next && chain->next->off)
144*c43e99fdSEd Maste 			w += (size_t)(chain->buffer_len - (chain->misalign + chain->off));
145*c43e99fdSEd Maste 		chain = chain->next;
146*c43e99fdSEd Maste 	}
147*c43e99fdSEd Maste 	/* subsequent nonempty chains */
148*c43e99fdSEd Maste 	while (chain && chain->off) {
149*c43e99fdSEd Maste 		++n;
150*c43e99fdSEd Maste 		a += chain->buffer_len;
151*c43e99fdSEd Maste 		w += (size_t)chain->misalign;
152*c43e99fdSEd Maste 		u += chain->off;
153*c43e99fdSEd Maste 		if (chain->next && chain->next->off)
154*c43e99fdSEd Maste 			w += (size_t) (chain->buffer_len - (chain->misalign + chain->off));
155*c43e99fdSEd Maste 		chain = chain->next;
156*c43e99fdSEd Maste 	}
157*c43e99fdSEd Maste 	/* subsequent empty chains */
158*c43e99fdSEd Maste 	while (chain) {
159*c43e99fdSEd Maste 		++n;
160*c43e99fdSEd Maste 		a += chain->buffer_len;
161*c43e99fdSEd Maste 	}
162*c43e99fdSEd Maste 	*allocatedp = a;
163*c43e99fdSEd Maste 	*wastedp = w;
164*c43e99fdSEd Maste 	*usedp = u;
165*c43e99fdSEd Maste }
166*c43e99fdSEd Maste 
167*c43e99fdSEd Maste #define evbuffer_validate(buf)			\
168*c43e99fdSEd Maste 	TT_STMT_BEGIN if (!evbuffer_validate_(buf)) TT_DIE(("Buffer format invalid")); TT_STMT_END
169*c43e99fdSEd Maste 
170*c43e99fdSEd Maste static void
171*c43e99fdSEd Maste test_evbuffer(void *ptr)
172*c43e99fdSEd Maste {
173*c43e99fdSEd Maste 	static char buffer[512], *tmp;
174*c43e99fdSEd Maste 	struct evbuffer *evb = evbuffer_new();
175*c43e99fdSEd Maste 	struct evbuffer *evb_two = evbuffer_new();
176*c43e99fdSEd Maste 	size_t sz_tmp;
177*c43e99fdSEd Maste 	int i;
178*c43e99fdSEd Maste 
179*c43e99fdSEd Maste 	evbuffer_validate(evb);
180*c43e99fdSEd Maste 	evbuffer_add_printf(evb, "%s/%d", "hello", 1);
181*c43e99fdSEd Maste 	evbuffer_validate(evb);
182*c43e99fdSEd Maste 
183*c43e99fdSEd Maste 	tt_assert(evbuffer_get_length(evb) == 7);
184*c43e99fdSEd Maste 	tt_assert(!memcmp((char*)EVBUFFER_DATA(evb), "hello/1", 1));
185*c43e99fdSEd Maste 
186*c43e99fdSEd Maste 	evbuffer_add_buffer(evb, evb_two);
187*c43e99fdSEd Maste 	evbuffer_validate(evb);
188*c43e99fdSEd Maste 
189*c43e99fdSEd Maste 	evbuffer_drain(evb, strlen("hello/"));
190*c43e99fdSEd Maste 	evbuffer_validate(evb);
191*c43e99fdSEd Maste 	tt_assert(evbuffer_get_length(evb) == 1);
192*c43e99fdSEd Maste 	tt_assert(!memcmp((char*)EVBUFFER_DATA(evb), "1", 1));
193*c43e99fdSEd Maste 
194*c43e99fdSEd Maste 	evbuffer_add_printf(evb_two, "%s", "/hello");
195*c43e99fdSEd Maste 	evbuffer_validate(evb);
196*c43e99fdSEd Maste 	evbuffer_add_buffer(evb, evb_two);
197*c43e99fdSEd Maste 	evbuffer_validate(evb);
198*c43e99fdSEd Maste 
199*c43e99fdSEd Maste 	tt_assert(evbuffer_get_length(evb_two) == 0);
200*c43e99fdSEd Maste 	tt_assert(evbuffer_get_length(evb) == 7);
201*c43e99fdSEd Maste 	tt_assert(!memcmp((char*)EVBUFFER_DATA(evb), "1/hello", 7));
202*c43e99fdSEd Maste 
203*c43e99fdSEd Maste 	memset(buffer, 0, sizeof(buffer));
204*c43e99fdSEd Maste 	evbuffer_add(evb, buffer, sizeof(buffer));
205*c43e99fdSEd Maste 	evbuffer_validate(evb);
206*c43e99fdSEd Maste 	tt_assert(evbuffer_get_length(evb) == 7 + 512);
207*c43e99fdSEd Maste 
208*c43e99fdSEd Maste 	tmp = (char *)evbuffer_pullup(evb, 7 + 512);
209*c43e99fdSEd Maste 	tt_assert(tmp);
210*c43e99fdSEd Maste 	tt_assert(!strncmp(tmp, "1/hello", 7));
211*c43e99fdSEd Maste 	tt_assert(!memcmp(tmp + 7, buffer, sizeof(buffer)));
212*c43e99fdSEd Maste 	evbuffer_validate(evb);
213*c43e99fdSEd Maste 
214*c43e99fdSEd Maste 	evbuffer_prepend(evb, "something", 9);
215*c43e99fdSEd Maste 	evbuffer_validate(evb);
216*c43e99fdSEd Maste 	evbuffer_prepend(evb, "else", 4);
217*c43e99fdSEd Maste 	evbuffer_validate(evb);
218*c43e99fdSEd Maste 
219*c43e99fdSEd Maste 	tmp = (char *)evbuffer_pullup(evb, 4 + 9 + 7);
220*c43e99fdSEd Maste 	tt_assert(!strncmp(tmp, "elsesomething1/hello", 4 + 9 + 7));
221*c43e99fdSEd Maste 	evbuffer_validate(evb);
222*c43e99fdSEd Maste 
223*c43e99fdSEd Maste 	evbuffer_drain(evb, -1);
224*c43e99fdSEd Maste 	evbuffer_validate(evb);
225*c43e99fdSEd Maste 	evbuffer_drain(evb_two, -1);
226*c43e99fdSEd Maste 	evbuffer_validate(evb);
227*c43e99fdSEd Maste 
228*c43e99fdSEd Maste 	for (i = 0; i < 3; ++i) {
229*c43e99fdSEd Maste 		evbuffer_add(evb_two, buffer, sizeof(buffer));
230*c43e99fdSEd Maste 		evbuffer_validate(evb_two);
231*c43e99fdSEd Maste 		evbuffer_add_buffer(evb, evb_two);
232*c43e99fdSEd Maste 		evbuffer_validate(evb);
233*c43e99fdSEd Maste 		evbuffer_validate(evb_two);
234*c43e99fdSEd Maste 	}
235*c43e99fdSEd Maste 
236*c43e99fdSEd Maste 	tt_assert(evbuffer_get_length(evb_two) == 0);
237*c43e99fdSEd Maste 	tt_assert(evbuffer_get_length(evb) == i * sizeof(buffer));
238*c43e99fdSEd Maste 
239*c43e99fdSEd Maste 	/* test remove buffer */
240*c43e99fdSEd Maste 	sz_tmp = (size_t)(sizeof(buffer)*2.5);
241*c43e99fdSEd Maste 	evbuffer_remove_buffer(evb, evb_two, sz_tmp);
242*c43e99fdSEd Maste 	tt_assert(evbuffer_get_length(evb_two) == sz_tmp);
243*c43e99fdSEd Maste 	tt_assert(evbuffer_get_length(evb) == sizeof(buffer) / 2);
244*c43e99fdSEd Maste 	evbuffer_validate(evb);
245*c43e99fdSEd Maste 
246*c43e99fdSEd Maste 	if (memcmp(evbuffer_pullup(
247*c43e99fdSEd Maste 			   evb, -1), buffer, sizeof(buffer) / 2) != 0 ||
248*c43e99fdSEd Maste 	    memcmp(evbuffer_pullup(
249*c43e99fdSEd Maste 			   evb_two, -1), buffer, sizeof(buffer)) != 0)
250*c43e99fdSEd Maste 		tt_abort_msg("Pullup did not preserve content");
251*c43e99fdSEd Maste 
252*c43e99fdSEd Maste 	evbuffer_validate(evb);
253*c43e99fdSEd Maste 
254*c43e99fdSEd Maste 
255*c43e99fdSEd Maste 	/* testing one-vector reserve and commit */
256*c43e99fdSEd Maste 	{
257*c43e99fdSEd Maste 		struct evbuffer_iovec v[1];
258*c43e99fdSEd Maste 		char *buf;
259*c43e99fdSEd Maste 		int i, j, r;
260*c43e99fdSEd Maste 
261*c43e99fdSEd Maste 		for (i = 0; i < 3; ++i) {
262*c43e99fdSEd Maste 			r = evbuffer_reserve_space(evb, 10000, v, 1);
263*c43e99fdSEd Maste 			tt_int_op(r, ==, 1);
264*c43e99fdSEd Maste 			tt_assert(v[0].iov_len >= 10000);
265*c43e99fdSEd Maste 			tt_assert(v[0].iov_base != NULL);
266*c43e99fdSEd Maste 
267*c43e99fdSEd Maste 			evbuffer_validate(evb);
268*c43e99fdSEd Maste 			buf = v[0].iov_base;
269*c43e99fdSEd Maste 			for (j = 0; j < 10000; ++j) {
270*c43e99fdSEd Maste 				buf[j] = j;
271*c43e99fdSEd Maste 			}
272*c43e99fdSEd Maste 			evbuffer_validate(evb);
273*c43e99fdSEd Maste 
274*c43e99fdSEd Maste 			tt_int_op(evbuffer_commit_space(evb, v, 1), ==, 0);
275*c43e99fdSEd Maste 			evbuffer_validate(evb);
276*c43e99fdSEd Maste 
277*c43e99fdSEd Maste 			tt_assert(evbuffer_get_length(evb) >= 10000);
278*c43e99fdSEd Maste 
279*c43e99fdSEd Maste 			evbuffer_drain(evb, j * 5000);
280*c43e99fdSEd Maste 			evbuffer_validate(evb);
281*c43e99fdSEd Maste 		}
282*c43e99fdSEd Maste 	}
283*c43e99fdSEd Maste 
284*c43e99fdSEd Maste  end:
285*c43e99fdSEd Maste 	evbuffer_free(evb);
286*c43e99fdSEd Maste 	evbuffer_free(evb_two);
287*c43e99fdSEd Maste }
288*c43e99fdSEd Maste 
289*c43e99fdSEd Maste static void
290*c43e99fdSEd Maste no_cleanup(const void *data, size_t datalen, void *extra)
291*c43e99fdSEd Maste {
292*c43e99fdSEd Maste }
293*c43e99fdSEd Maste 
294*c43e99fdSEd Maste static void
295*c43e99fdSEd Maste test_evbuffer_remove_buffer_with_empty(void *ptr)
296*c43e99fdSEd Maste {
297*c43e99fdSEd Maste     struct evbuffer *src = evbuffer_new();
298*c43e99fdSEd Maste     struct evbuffer *dst = evbuffer_new();
299*c43e99fdSEd Maste     char buf[2];
300*c43e99fdSEd Maste 
301*c43e99fdSEd Maste     evbuffer_validate(src);
302*c43e99fdSEd Maste     evbuffer_validate(dst);
303*c43e99fdSEd Maste 
304*c43e99fdSEd Maste     /* setup the buffers */
305*c43e99fdSEd Maste     /* we need more data in src than we will move later */
306*c43e99fdSEd Maste     evbuffer_add_reference(src, buf, sizeof(buf), no_cleanup, NULL);
307*c43e99fdSEd Maste     evbuffer_add_reference(src, buf, sizeof(buf), no_cleanup, NULL);
308*c43e99fdSEd Maste     /* we need one buffer in dst and one empty buffer at the end */
309*c43e99fdSEd Maste     evbuffer_add(dst, buf, sizeof(buf));
310*c43e99fdSEd Maste     evbuffer_add_reference(dst, buf, 0, no_cleanup, NULL);
311*c43e99fdSEd Maste 
312*c43e99fdSEd Maste     evbuffer_validate(src);
313*c43e99fdSEd Maste     evbuffer_validate(dst);
314*c43e99fdSEd Maste 
315*c43e99fdSEd Maste     /* move three bytes over */
316*c43e99fdSEd Maste     evbuffer_remove_buffer(src, dst, 3);
317*c43e99fdSEd Maste 
318*c43e99fdSEd Maste     evbuffer_validate(src);
319*c43e99fdSEd Maste     evbuffer_validate(dst);
320*c43e99fdSEd Maste 
321*c43e99fdSEd Maste end:
322*c43e99fdSEd Maste     evbuffer_free(src);
323*c43e99fdSEd Maste     evbuffer_free(dst);
324*c43e99fdSEd Maste }
325*c43e99fdSEd Maste 
326*c43e99fdSEd Maste static void
327*c43e99fdSEd Maste test_evbuffer_remove_buffer_with_empty2(void *ptr)
328*c43e99fdSEd Maste {
329*c43e99fdSEd Maste 	struct evbuffer *src = evbuffer_new();
330*c43e99fdSEd Maste 	struct evbuffer *dst = evbuffer_new();
331*c43e99fdSEd Maste 	struct evbuffer *buf = evbuffer_new();
332*c43e99fdSEd Maste 
333*c43e99fdSEd Maste 	evbuffer_add(buf, "foo", 3);
334*c43e99fdSEd Maste 	evbuffer_add_reference(buf, "foo", 3, NULL, NULL);
335*c43e99fdSEd Maste 
336*c43e99fdSEd Maste 	evbuffer_add_reference(src, "foo", 3, NULL, NULL);
337*c43e99fdSEd Maste 	evbuffer_add_reference(src, NULL, 0, NULL, NULL);
338*c43e99fdSEd Maste 	evbuffer_add_buffer(src, buf);
339*c43e99fdSEd Maste 
340*c43e99fdSEd Maste 	evbuffer_add(buf, "foo", 3);
341*c43e99fdSEd Maste 	evbuffer_add_reference(buf, "foo", 3, NULL, NULL);
342*c43e99fdSEd Maste 
343*c43e99fdSEd Maste 	evbuffer_add_reference(dst, "foo", 3, NULL, NULL);
344*c43e99fdSEd Maste 	evbuffer_add_reference(dst, NULL, 0, NULL, NULL);
345*c43e99fdSEd Maste 	evbuffer_add_buffer(dst, buf);
346*c43e99fdSEd Maste 
347*c43e99fdSEd Maste 	tt_int_op(evbuffer_get_length(src), ==, 9);
348*c43e99fdSEd Maste 	tt_int_op(evbuffer_get_length(dst), ==, 9);
349*c43e99fdSEd Maste 
350*c43e99fdSEd Maste 	evbuffer_validate(src);
351*c43e99fdSEd Maste 	evbuffer_validate(dst);
352*c43e99fdSEd Maste 
353*c43e99fdSEd Maste 	evbuffer_remove_buffer(src, dst, 8);
354*c43e99fdSEd Maste 
355*c43e99fdSEd Maste 	evbuffer_validate(src);
356*c43e99fdSEd Maste 	evbuffer_validate(dst);
357*c43e99fdSEd Maste 
358*c43e99fdSEd Maste 	tt_int_op(evbuffer_get_length(src), ==, 1);
359*c43e99fdSEd Maste 	tt_int_op(evbuffer_get_length(dst), ==, 17);
360*c43e99fdSEd Maste 
361*c43e99fdSEd Maste  end:
362*c43e99fdSEd Maste 	evbuffer_free(src);
363*c43e99fdSEd Maste 	evbuffer_free(dst);
364*c43e99fdSEd Maste 	evbuffer_free(buf);
365*c43e99fdSEd Maste }
366*c43e99fdSEd Maste 
367*c43e99fdSEd Maste static void
368*c43e99fdSEd Maste test_evbuffer_remove_buffer_with_empty3(void *ptr)
369*c43e99fdSEd Maste {
370*c43e99fdSEd Maste 	struct evbuffer *src = evbuffer_new();
371*c43e99fdSEd Maste 	struct evbuffer *dst = evbuffer_new();
372*c43e99fdSEd Maste 	struct evbuffer *buf = evbuffer_new();
373*c43e99fdSEd Maste 
374*c43e99fdSEd Maste 	evbuffer_add(buf, "foo", 3);
375*c43e99fdSEd Maste 	evbuffer_add_reference(buf, NULL, 0, NULL, NULL);
376*c43e99fdSEd Maste 
377*c43e99fdSEd Maste 	evbuffer_add_reference(src, "foo", 3, NULL, NULL);
378*c43e99fdSEd Maste 	evbuffer_add_reference(src, NULL, 0, NULL, NULL);
379*c43e99fdSEd Maste 	evbuffer_prepend_buffer(src, buf);
380*c43e99fdSEd Maste 
381*c43e99fdSEd Maste 	evbuffer_add(buf, "foo", 3);
382*c43e99fdSEd Maste 	evbuffer_add_reference(buf, NULL, 0, NULL, NULL);
383*c43e99fdSEd Maste 
384*c43e99fdSEd Maste 	evbuffer_add_reference(dst, "foo", 3, NULL, NULL);
385*c43e99fdSEd Maste 	evbuffer_add_reference(dst, NULL, 0, NULL, NULL);
386*c43e99fdSEd Maste 	evbuffer_prepend_buffer(dst, buf);
387*c43e99fdSEd Maste 
388*c43e99fdSEd Maste 	tt_int_op(evbuffer_get_length(src), ==, 6);
389*c43e99fdSEd Maste 	tt_int_op(evbuffer_get_length(dst), ==, 6);
390*c43e99fdSEd Maste 
391*c43e99fdSEd Maste 	evbuffer_validate(src);
392*c43e99fdSEd Maste 	evbuffer_validate(dst);
393*c43e99fdSEd Maste 
394*c43e99fdSEd Maste 	evbuffer_remove_buffer(src, dst, 5);
395*c43e99fdSEd Maste 
396*c43e99fdSEd Maste 	evbuffer_validate(src);
397*c43e99fdSEd Maste 	evbuffer_validate(dst);
398*c43e99fdSEd Maste 
399*c43e99fdSEd Maste 	tt_int_op(evbuffer_get_length(src), ==, 1);
400*c43e99fdSEd Maste 	tt_int_op(evbuffer_get_length(dst), ==, 11);
401*c43e99fdSEd Maste 
402*c43e99fdSEd Maste  end:
403*c43e99fdSEd Maste 	evbuffer_free(src);
404*c43e99fdSEd Maste 	evbuffer_free(dst);
405*c43e99fdSEd Maste 	evbuffer_free(buf);
406*c43e99fdSEd Maste }
407*c43e99fdSEd Maste 
408*c43e99fdSEd Maste static void
409*c43e99fdSEd Maste test_evbuffer_add_buffer_with_empty(void *ptr)
410*c43e99fdSEd Maste {
411*c43e99fdSEd Maste 	struct evbuffer *src = evbuffer_new();
412*c43e99fdSEd Maste 	struct evbuffer *dst = evbuffer_new();
413*c43e99fdSEd Maste 	struct evbuffer *buf = evbuffer_new();
414*c43e99fdSEd Maste 
415*c43e99fdSEd Maste 	evbuffer_add(buf, "foo", 3);
416*c43e99fdSEd Maste 
417*c43e99fdSEd Maste 	evbuffer_add_reference(src, "foo", 3, NULL, NULL);
418*c43e99fdSEd Maste 	evbuffer_add_reference(src, NULL, 0, NULL, NULL);
419*c43e99fdSEd Maste 	evbuffer_add_buffer(src, buf);
420*c43e99fdSEd Maste 
421*c43e99fdSEd Maste 	evbuffer_add(buf, "foo", 3);
422*c43e99fdSEd Maste 
423*c43e99fdSEd Maste 	evbuffer_add_reference(dst, "foo", 3, NULL, NULL);
424*c43e99fdSEd Maste 	evbuffer_add_reference(dst, NULL, 0, NULL, NULL);
425*c43e99fdSEd Maste 	evbuffer_add_buffer(dst, buf);
426*c43e99fdSEd Maste 
427*c43e99fdSEd Maste 	tt_int_op(evbuffer_get_length(src), ==, 6);
428*c43e99fdSEd Maste 	tt_int_op(evbuffer_get_length(dst), ==, 6);
429*c43e99fdSEd Maste 
430*c43e99fdSEd Maste 	evbuffer_validate(src);
431*c43e99fdSEd Maste 	evbuffer_validate(dst);
432*c43e99fdSEd Maste 
433*c43e99fdSEd Maste  end:
434*c43e99fdSEd Maste 	evbuffer_free(src);
435*c43e99fdSEd Maste 	evbuffer_free(dst);
436*c43e99fdSEd Maste 	evbuffer_free(buf);
437*c43e99fdSEd Maste }
438*c43e99fdSEd Maste 
439*c43e99fdSEd Maste static void
440*c43e99fdSEd Maste test_evbuffer_add_buffer_with_empty2(void *ptr)
441*c43e99fdSEd Maste {
442*c43e99fdSEd Maste 	struct evbuffer *src = evbuffer_new();
443*c43e99fdSEd Maste 	struct evbuffer *dst = evbuffer_new();
444*c43e99fdSEd Maste 	struct evbuffer *buf = evbuffer_new();
445*c43e99fdSEd Maste 
446*c43e99fdSEd Maste 	evbuffer_add(buf, "foo", 3);
447*c43e99fdSEd Maste 
448*c43e99fdSEd Maste 	evbuffer_add_reference(src, NULL, 0, NULL, NULL);
449*c43e99fdSEd Maste 	evbuffer_add_buffer(src, buf);
450*c43e99fdSEd Maste 
451*c43e99fdSEd Maste 	evbuffer_add(buf, "foo", 3);
452*c43e99fdSEd Maste 
453*c43e99fdSEd Maste 	evbuffer_add_reference(dst, NULL, 0, NULL, NULL);
454*c43e99fdSEd Maste 	evbuffer_add_buffer(dst, buf);
455*c43e99fdSEd Maste 
456*c43e99fdSEd Maste 	tt_int_op(evbuffer_get_length(src), ==, 3);
457*c43e99fdSEd Maste 	tt_int_op(evbuffer_get_length(dst), ==, 3);
458*c43e99fdSEd Maste 
459*c43e99fdSEd Maste 	evbuffer_validate(src);
460*c43e99fdSEd Maste 	evbuffer_validate(dst);
461*c43e99fdSEd Maste 
462*c43e99fdSEd Maste  end:
463*c43e99fdSEd Maste 	evbuffer_free(src);
464*c43e99fdSEd Maste 	evbuffer_free(dst);
465*c43e99fdSEd Maste 	evbuffer_free(buf);
466*c43e99fdSEd Maste }
467*c43e99fdSEd Maste 
468*c43e99fdSEd Maste static void
469*c43e99fdSEd Maste test_evbuffer_reserve2(void *ptr)
470*c43e99fdSEd Maste {
471*c43e99fdSEd Maste 	/* Test the two-vector cases of reserve/commit. */
472*c43e99fdSEd Maste 	struct evbuffer *buf = evbuffer_new();
473*c43e99fdSEd Maste 	int n, i;
474*c43e99fdSEd Maste 	struct evbuffer_iovec v[2];
475*c43e99fdSEd Maste 	size_t remaining;
476*c43e99fdSEd Maste 	char *cp, *cp2;
477*c43e99fdSEd Maste 
478*c43e99fdSEd Maste 	/* First chunk will necessarily be one chunk. Use 512 bytes of it.*/
479*c43e99fdSEd Maste 	n = evbuffer_reserve_space(buf, 1024, v, 2);
480*c43e99fdSEd Maste 	tt_int_op(n, ==, 1);
481*c43e99fdSEd Maste 	tt_int_op(evbuffer_get_length(buf), ==, 0);
482*c43e99fdSEd Maste 	tt_assert(v[0].iov_base != NULL);
483*c43e99fdSEd Maste 	tt_int_op(v[0].iov_len, >=, 1024);
484*c43e99fdSEd Maste 	memset(v[0].iov_base, 'X', 512);
485*c43e99fdSEd Maste 	cp = v[0].iov_base;
486*c43e99fdSEd Maste 	remaining = v[0].iov_len - 512;
487*c43e99fdSEd Maste 	v[0].iov_len = 512;
488*c43e99fdSEd Maste 	evbuffer_validate(buf);
489*c43e99fdSEd Maste 	tt_int_op(0, ==, evbuffer_commit_space(buf, v, 1));
490*c43e99fdSEd Maste 	tt_int_op(evbuffer_get_length(buf), ==, 512);
491*c43e99fdSEd Maste 	evbuffer_validate(buf);
492*c43e99fdSEd Maste 
493*c43e99fdSEd Maste 	/* Ask for another same-chunk request, in an existing chunk. Use 8
494*c43e99fdSEd Maste 	 * bytes of it. */
495*c43e99fdSEd Maste 	n = evbuffer_reserve_space(buf, 32, v, 2);
496*c43e99fdSEd Maste 	tt_int_op(n, ==, 1);
497*c43e99fdSEd Maste 	tt_assert(cp + 512 == v[0].iov_base);
498*c43e99fdSEd Maste 	tt_int_op(remaining, ==, v[0].iov_len);
499*c43e99fdSEd Maste 	memset(v[0].iov_base, 'Y', 8);
500*c43e99fdSEd Maste 	v[0].iov_len = 8;
501*c43e99fdSEd Maste 	tt_int_op(0, ==, evbuffer_commit_space(buf, v, 1));
502*c43e99fdSEd Maste 	tt_int_op(evbuffer_get_length(buf), ==, 520);
503*c43e99fdSEd Maste 	remaining -= 8;
504*c43e99fdSEd Maste 	evbuffer_validate(buf);
505*c43e99fdSEd Maste 
506*c43e99fdSEd Maste 	/* Now ask for a request that will be split. Use only one byte of it,
507*c43e99fdSEd Maste 	   though. */
508*c43e99fdSEd Maste 	n = evbuffer_reserve_space(buf, remaining+64, v, 2);
509*c43e99fdSEd Maste 	tt_int_op(n, ==, 2);
510*c43e99fdSEd Maste 	tt_assert(cp + 520 == v[0].iov_base);
511*c43e99fdSEd Maste 	tt_int_op(remaining, ==, v[0].iov_len);
512*c43e99fdSEd Maste 	tt_assert(v[1].iov_base);
513*c43e99fdSEd Maste 	tt_assert(v[1].iov_len >= 64);
514*c43e99fdSEd Maste 	cp2 = v[1].iov_base;
515*c43e99fdSEd Maste 	memset(v[0].iov_base, 'Z', 1);
516*c43e99fdSEd Maste 	v[0].iov_len = 1;
517*c43e99fdSEd Maste 	tt_int_op(0, ==, evbuffer_commit_space(buf, v, 1));
518*c43e99fdSEd Maste 	tt_int_op(evbuffer_get_length(buf), ==, 521);
519*c43e99fdSEd Maste 	remaining -= 1;
520*c43e99fdSEd Maste 	evbuffer_validate(buf);
521*c43e99fdSEd Maste 
522*c43e99fdSEd Maste 	/* Now ask for a request that will be split. Use some of the first
523*c43e99fdSEd Maste 	 * part and some of the second. */
524*c43e99fdSEd Maste 	n = evbuffer_reserve_space(buf, remaining+64, v, 2);
525*c43e99fdSEd Maste 	evbuffer_validate(buf);
526*c43e99fdSEd Maste 	tt_int_op(n, ==, 2);
527*c43e99fdSEd Maste 	tt_assert(cp + 521 == v[0].iov_base);
528*c43e99fdSEd Maste 	tt_int_op(remaining, ==, v[0].iov_len);
529*c43e99fdSEd Maste 	tt_assert(v[1].iov_base == cp2);
530*c43e99fdSEd Maste 	tt_assert(v[1].iov_len >= 64);
531*c43e99fdSEd Maste 	memset(v[0].iov_base, 'W', 400);
532*c43e99fdSEd Maste 	v[0].iov_len = 400;
533*c43e99fdSEd Maste 	memset(v[1].iov_base, 'x', 60);
534*c43e99fdSEd Maste 	v[1].iov_len = 60;
535*c43e99fdSEd Maste 	tt_int_op(0, ==, evbuffer_commit_space(buf, v, 2));
536*c43e99fdSEd Maste 	tt_int_op(evbuffer_get_length(buf), ==, 981);
537*c43e99fdSEd Maste 	evbuffer_validate(buf);
538*c43e99fdSEd Maste 
539*c43e99fdSEd Maste 	/* Now peek to make sure stuff got made how we like. */
540*c43e99fdSEd Maste 	memset(v,0,sizeof(v));
541*c43e99fdSEd Maste 	n = evbuffer_peek(buf, -1, NULL, v, 2);
542*c43e99fdSEd Maste 	tt_int_op(n, ==, 2);
543*c43e99fdSEd Maste 	tt_int_op(v[0].iov_len, ==, 921);
544*c43e99fdSEd Maste 	tt_int_op(v[1].iov_len, ==, 60);
545*c43e99fdSEd Maste 
546*c43e99fdSEd Maste 	cp = v[0].iov_base;
547*c43e99fdSEd Maste 	for (i=0; i<512; ++i)
548*c43e99fdSEd Maste 		tt_int_op(cp[i], ==, 'X');
549*c43e99fdSEd Maste 	for (i=512; i<520; ++i)
550*c43e99fdSEd Maste 		tt_int_op(cp[i], ==, 'Y');
551*c43e99fdSEd Maste 	for (i=520; i<521; ++i)
552*c43e99fdSEd Maste 		tt_int_op(cp[i], ==, 'Z');
553*c43e99fdSEd Maste 	for (i=521; i<921; ++i)
554*c43e99fdSEd Maste 		tt_int_op(cp[i], ==, 'W');
555*c43e99fdSEd Maste 
556*c43e99fdSEd Maste 	cp = v[1].iov_base;
557*c43e99fdSEd Maste 	for (i=0; i<60; ++i)
558*c43e99fdSEd Maste 		tt_int_op(cp[i], ==, 'x');
559*c43e99fdSEd Maste 
560*c43e99fdSEd Maste end:
561*c43e99fdSEd Maste 	evbuffer_free(buf);
562*c43e99fdSEd Maste }
563*c43e99fdSEd Maste 
564*c43e99fdSEd Maste static void
565*c43e99fdSEd Maste test_evbuffer_reserve_many(void *ptr)
566*c43e99fdSEd Maste {
567*c43e99fdSEd Maste 	/* This is a glass-box test to handle expanding a buffer with more
568*c43e99fdSEd Maste 	 * chunks and reallocating chunks as needed */
569*c43e99fdSEd Maste 	struct evbuffer *buf = evbuffer_new();
570*c43e99fdSEd Maste 	struct evbuffer_iovec v[8];
571*c43e99fdSEd Maste 	int n;
572*c43e99fdSEd Maste 	size_t sz;
573*c43e99fdSEd Maste 	int add_data = ptr && !strcmp(ptr, "add");
574*c43e99fdSEd Maste 	int fill_first = ptr && !strcmp(ptr, "fill");
575*c43e99fdSEd Maste 	char *cp1, *cp2;
576*c43e99fdSEd Maste 
577*c43e99fdSEd Maste 	/* When reserving the the first chunk, we just allocate it */
578*c43e99fdSEd Maste 	n = evbuffer_reserve_space(buf, 128, v, 2);
579*c43e99fdSEd Maste 	evbuffer_validate(buf);
580*c43e99fdSEd Maste 	tt_int_op(n, ==, 1);
581*c43e99fdSEd Maste 	tt_assert(v[0].iov_len >= 128);
582*c43e99fdSEd Maste 	sz = v[0].iov_len;
583*c43e99fdSEd Maste 	cp1 = v[0].iov_base;
584*c43e99fdSEd Maste 	if (add_data) {
585*c43e99fdSEd Maste 		*(char*)v[0].iov_base = 'X';
586*c43e99fdSEd Maste 		v[0].iov_len = 1;
587*c43e99fdSEd Maste 		n = evbuffer_commit_space(buf, v, 1);
588*c43e99fdSEd Maste 		tt_int_op(n, ==, 0);
589*c43e99fdSEd Maste 	} else if (fill_first) {
590*c43e99fdSEd Maste 		memset(v[0].iov_base, 'X', v[0].iov_len);
591*c43e99fdSEd Maste 		n = evbuffer_commit_space(buf, v, 1);
592*c43e99fdSEd Maste 		tt_int_op(n, ==, 0);
593*c43e99fdSEd Maste 		n = evbuffer_reserve_space(buf, 128, v, 2);
594*c43e99fdSEd Maste 		tt_int_op(n, ==, 1);
595*c43e99fdSEd Maste 		sz = v[0].iov_len;
596*c43e99fdSEd Maste 		tt_assert(v[0].iov_base != cp1);
597*c43e99fdSEd Maste 		cp1 = v[0].iov_base;
598*c43e99fdSEd Maste 	}
599*c43e99fdSEd Maste 
600*c43e99fdSEd Maste 	/* Make another chunk get added. */
601*c43e99fdSEd Maste 	n = evbuffer_reserve_space(buf, sz+128, v, 2);
602*c43e99fdSEd Maste 	evbuffer_validate(buf);
603*c43e99fdSEd Maste 	tt_int_op(n, ==, 2);
604*c43e99fdSEd Maste 	sz = v[0].iov_len + v[1].iov_len;
605*c43e99fdSEd Maste 	tt_int_op(sz, >=, v[0].iov_len+128);
606*c43e99fdSEd Maste 	if (add_data) {
607*c43e99fdSEd Maste 		tt_assert(v[0].iov_base == cp1 + 1);
608*c43e99fdSEd Maste 	} else {
609*c43e99fdSEd Maste 		tt_assert(v[0].iov_base == cp1);
610*c43e99fdSEd Maste 	}
611*c43e99fdSEd Maste 	cp1 = v[0].iov_base;
612*c43e99fdSEd Maste 	cp2 = v[1].iov_base;
613*c43e99fdSEd Maste 
614*c43e99fdSEd Maste 	/* And a third chunk. */
615*c43e99fdSEd Maste 	n = evbuffer_reserve_space(buf, sz+128, v, 3);
616*c43e99fdSEd Maste 	evbuffer_validate(buf);
617*c43e99fdSEd Maste 	tt_int_op(n, ==, 3);
618*c43e99fdSEd Maste 	tt_assert(cp1 == v[0].iov_base);
619*c43e99fdSEd Maste 	tt_assert(cp2 == v[1].iov_base);
620*c43e99fdSEd Maste 	sz = v[0].iov_len + v[1].iov_len + v[2].iov_len;
621*c43e99fdSEd Maste 
622*c43e99fdSEd Maste 	/* Now force a reallocation by asking for more space in only 2
623*c43e99fdSEd Maste 	 * buffers. */
624*c43e99fdSEd Maste 	n = evbuffer_reserve_space(buf, sz+128, v, 2);
625*c43e99fdSEd Maste 	evbuffer_validate(buf);
626*c43e99fdSEd Maste 	if (add_data) {
627*c43e99fdSEd Maste 		tt_int_op(n, ==, 2);
628*c43e99fdSEd Maste 		tt_assert(cp1 == v[0].iov_base);
629*c43e99fdSEd Maste 	} else {
630*c43e99fdSEd Maste 		tt_int_op(n, ==, 1);
631*c43e99fdSEd Maste 	}
632*c43e99fdSEd Maste 
633*c43e99fdSEd Maste end:
634*c43e99fdSEd Maste 	evbuffer_free(buf);
635*c43e99fdSEd Maste }
636*c43e99fdSEd Maste 
637*c43e99fdSEd Maste static void
638*c43e99fdSEd Maste test_evbuffer_expand(void *ptr)
639*c43e99fdSEd Maste {
640*c43e99fdSEd Maste 	char data[4096];
641*c43e99fdSEd Maste 	struct evbuffer *buf;
642*c43e99fdSEd Maste 	size_t a,w,u;
643*c43e99fdSEd Maste 	void *buffer;
644*c43e99fdSEd Maste 
645*c43e99fdSEd Maste 	memset(data, 'X', sizeof(data));
646*c43e99fdSEd Maste 
647*c43e99fdSEd Maste 	/* Make sure that expand() works on an empty buffer */
648*c43e99fdSEd Maste 	buf = evbuffer_new();
649*c43e99fdSEd Maste 	tt_int_op(evbuffer_expand(buf, 20000), ==, 0);
650*c43e99fdSEd Maste 	evbuffer_validate(buf);
651*c43e99fdSEd Maste 	a=w=u=0;
652*c43e99fdSEd Maste 	evbuffer_get_waste(buf, &a,&w,&u);
653*c43e99fdSEd Maste 	tt_assert(w == 0);
654*c43e99fdSEd Maste 	tt_assert(u == 0);
655*c43e99fdSEd Maste 	tt_assert(a >= 20000);
656*c43e99fdSEd Maste 	tt_assert(buf->first);
657*c43e99fdSEd Maste 	tt_assert(buf->first == buf->last);
658*c43e99fdSEd Maste 	tt_assert(buf->first->off == 0);
659*c43e99fdSEd Maste 	tt_assert(buf->first->buffer_len >= 20000);
660*c43e99fdSEd Maste 
661*c43e99fdSEd Maste 	/* Make sure that expand() works as a no-op when there's enough
662*c43e99fdSEd Maste 	 * contiguous space already. */
663*c43e99fdSEd Maste 	buffer = buf->first->buffer;
664*c43e99fdSEd Maste 	evbuffer_add(buf, data, 1024);
665*c43e99fdSEd Maste 	tt_int_op(evbuffer_expand(buf, 1024), ==, 0);
666*c43e99fdSEd Maste 	tt_assert(buf->first->buffer == buffer);
667*c43e99fdSEd Maste 	evbuffer_validate(buf);
668*c43e99fdSEd Maste 	evbuffer_free(buf);
669*c43e99fdSEd Maste 
670*c43e99fdSEd Maste 	/* Make sure that expand() can work by moving misaligned data
671*c43e99fdSEd Maste 	 * when it makes sense to do so. */
672*c43e99fdSEd Maste 	buf = evbuffer_new();
673*c43e99fdSEd Maste 	evbuffer_add(buf, data, 400);
674*c43e99fdSEd Maste 	{
675*c43e99fdSEd Maste 		int n = (int)(buf->first->buffer_len - buf->first->off - 1);
676*c43e99fdSEd Maste 		tt_assert(n < (int)sizeof(data));
677*c43e99fdSEd Maste 		evbuffer_add(buf, data, n);
678*c43e99fdSEd Maste 	}
679*c43e99fdSEd Maste 	tt_assert(buf->first == buf->last);
680*c43e99fdSEd Maste 	tt_assert(buf->first->off == buf->first->buffer_len - 1);
681*c43e99fdSEd Maste 	evbuffer_drain(buf, buf->first->off - 1);
682*c43e99fdSEd Maste 	tt_assert(1 == evbuffer_get_length(buf));
683*c43e99fdSEd Maste 	tt_assert(buf->first->misalign > 0);
684*c43e99fdSEd Maste 	tt_assert(buf->first->off == 1);
685*c43e99fdSEd Maste 	buffer = buf->first->buffer;
686*c43e99fdSEd Maste 	tt_assert(evbuffer_expand(buf, 40) == 0);
687*c43e99fdSEd Maste 	tt_assert(buf->first == buf->last);
688*c43e99fdSEd Maste 	tt_assert(buf->first->off == 1);
689*c43e99fdSEd Maste 	tt_assert(buf->first->buffer == buffer);
690*c43e99fdSEd Maste 	tt_assert(buf->first->misalign == 0);
691*c43e99fdSEd Maste 	evbuffer_validate(buf);
692*c43e99fdSEd Maste 	evbuffer_free(buf);
693*c43e99fdSEd Maste 
694*c43e99fdSEd Maste 	/* add, expand, pull-up: This used to crash libevent. */
695*c43e99fdSEd Maste 	buf = evbuffer_new();
696*c43e99fdSEd Maste 
697*c43e99fdSEd Maste 	evbuffer_add(buf, data, sizeof(data));
698*c43e99fdSEd Maste 	evbuffer_add(buf, data, sizeof(data));
699*c43e99fdSEd Maste 	evbuffer_add(buf, data, sizeof(data));
700*c43e99fdSEd Maste 
701*c43e99fdSEd Maste 	evbuffer_validate(buf);
702*c43e99fdSEd Maste 	evbuffer_expand(buf, 1024);
703*c43e99fdSEd Maste 	evbuffer_validate(buf);
704*c43e99fdSEd Maste 	evbuffer_pullup(buf, -1);
705*c43e99fdSEd Maste 	evbuffer_validate(buf);
706*c43e99fdSEd Maste 
707*c43e99fdSEd Maste end:
708*c43e99fdSEd Maste 	evbuffer_free(buf);
709*c43e99fdSEd Maste }
710*c43e99fdSEd Maste 
711*c43e99fdSEd Maste static void
712*c43e99fdSEd Maste test_evbuffer_expand_overflow(void *ptr)
713*c43e99fdSEd Maste {
714*c43e99fdSEd Maste 	struct evbuffer *buf;
715*c43e99fdSEd Maste 
716*c43e99fdSEd Maste 	buf = evbuffer_new();
717*c43e99fdSEd Maste 	evbuffer_add(buf, "1", 1);
718*c43e99fdSEd Maste 	evbuffer_expand(buf, EVBUFFER_CHAIN_MAX);
719*c43e99fdSEd Maste 	evbuffer_validate(buf);
720*c43e99fdSEd Maste 
721*c43e99fdSEd Maste 	evbuffer_expand(buf, EV_SIZE_MAX);
722*c43e99fdSEd Maste 	evbuffer_validate(buf);
723*c43e99fdSEd Maste 
724*c43e99fdSEd Maste end:
725*c43e99fdSEd Maste 	evbuffer_free(buf);
726*c43e99fdSEd Maste }
727*c43e99fdSEd Maste 
728*c43e99fdSEd Maste static void
729*c43e99fdSEd Maste test_evbuffer_add1(void *ptr)
730*c43e99fdSEd Maste {
731*c43e99fdSEd Maste 	struct evbuffer *buf;
732*c43e99fdSEd Maste 	char *str;
733*c43e99fdSEd Maste 
734*c43e99fdSEd Maste 	buf = evbuffer_new();
735*c43e99fdSEd Maste 	evbuffer_add(buf, "1", 1);
736*c43e99fdSEd Maste 	evbuffer_validate(buf);
737*c43e99fdSEd Maste 	evbuffer_expand(buf, 2048);
738*c43e99fdSEd Maste 	evbuffer_validate(buf);
739*c43e99fdSEd Maste 	evbuffer_add(buf, "2", 1);
740*c43e99fdSEd Maste 	evbuffer_validate(buf);
741*c43e99fdSEd Maste 	evbuffer_add_printf(buf, "3");
742*c43e99fdSEd Maste 	evbuffer_validate(buf);
743*c43e99fdSEd Maste 
744*c43e99fdSEd Maste 	tt_assert(evbuffer_get_length(buf) == 3);
745*c43e99fdSEd Maste 	str = (char *)evbuffer_pullup(buf, -1);
746*c43e99fdSEd Maste 	tt_assert(str[0] == '1');
747*c43e99fdSEd Maste 	tt_assert(str[1] == '2');
748*c43e99fdSEd Maste 	tt_assert(str[2] == '3');
749*c43e99fdSEd Maste end:
750*c43e99fdSEd Maste 	evbuffer_free(buf);
751*c43e99fdSEd Maste }
752*c43e99fdSEd Maste 
753*c43e99fdSEd Maste static void
754*c43e99fdSEd Maste test_evbuffer_add2(void *ptr)
755*c43e99fdSEd Maste {
756*c43e99fdSEd Maste 	struct evbuffer *buf;
757*c43e99fdSEd Maste 	static char data[4096];
758*c43e99fdSEd Maste 	int data_len = MIN_BUFFER_SIZE-EVBUFFER_CHAIN_SIZE-10;
759*c43e99fdSEd Maste 	char *str;
760*c43e99fdSEd Maste 	int len;
761*c43e99fdSEd Maste 
762*c43e99fdSEd Maste 	memset(data, 'P', sizeof(data));
763*c43e99fdSEd Maste 	buf = evbuffer_new();
764*c43e99fdSEd Maste 	evbuffer_add(buf, data, data_len);
765*c43e99fdSEd Maste 	evbuffer_validate(buf);
766*c43e99fdSEd Maste 	evbuffer_expand(buf, 100);
767*c43e99fdSEd Maste 	evbuffer_validate(buf);
768*c43e99fdSEd Maste 	evbuffer_add(buf, "2", 1);
769*c43e99fdSEd Maste 	evbuffer_validate(buf);
770*c43e99fdSEd Maste 	evbuffer_add_printf(buf, "3");
771*c43e99fdSEd Maste 	evbuffer_validate(buf);
772*c43e99fdSEd Maste 
773*c43e99fdSEd Maste 	len = evbuffer_get_length(buf);
774*c43e99fdSEd Maste 	tt_assert(len == data_len+2);
775*c43e99fdSEd Maste 	str = (char *)evbuffer_pullup(buf, -1);
776*c43e99fdSEd Maste 	tt_assert(str[len-3] == 'P');
777*c43e99fdSEd Maste 	tt_assert(str[len-2] == '2');
778*c43e99fdSEd Maste 	tt_assert(str[len-1] == '3');
779*c43e99fdSEd Maste end:
780*c43e99fdSEd Maste 	evbuffer_free(buf);
781*c43e99fdSEd Maste }
782*c43e99fdSEd Maste 
783*c43e99fdSEd Maste static int reference_cb_called;
784*c43e99fdSEd Maste static void
785*c43e99fdSEd Maste reference_cb(const void *data, size_t len, void *extra)
786*c43e99fdSEd Maste {
787*c43e99fdSEd Maste 	tt_str_op(data, ==, "this is what we add as read-only memory.");
788*c43e99fdSEd Maste 	tt_int_op(len, ==, strlen(data));
789*c43e99fdSEd Maste 	tt_want(extra == (void *)0xdeadaffe);
790*c43e99fdSEd Maste 	++reference_cb_called;
791*c43e99fdSEd Maste end:
792*c43e99fdSEd Maste 	;
793*c43e99fdSEd Maste }
794*c43e99fdSEd Maste 
795*c43e99fdSEd Maste static void
796*c43e99fdSEd Maste test_evbuffer_reference(void *ptr)
797*c43e99fdSEd Maste {
798*c43e99fdSEd Maste 	struct evbuffer *src = evbuffer_new();
799*c43e99fdSEd Maste 	struct evbuffer *dst = evbuffer_new();
800*c43e99fdSEd Maste 	struct evbuffer_iovec v[1];
801*c43e99fdSEd Maste 	const char *data = "this is what we add as read-only memory.";
802*c43e99fdSEd Maste 	reference_cb_called = 0;
803*c43e99fdSEd Maste 
804*c43e99fdSEd Maste 	tt_assert(evbuffer_add_reference(src, data, strlen(data),
805*c43e99fdSEd Maste 		 reference_cb, (void *)0xdeadaffe) != -1);
806*c43e99fdSEd Maste 
807*c43e99fdSEd Maste 	evbuffer_reserve_space(dst, strlen(data), v, 1);
808*c43e99fdSEd Maste 	tt_assert(evbuffer_remove(src, v[0].iov_base, 10) != -1);
809*c43e99fdSEd Maste 
810*c43e99fdSEd Maste 	evbuffer_validate(src);
811*c43e99fdSEd Maste 	evbuffer_validate(dst);
812*c43e99fdSEd Maste 
813*c43e99fdSEd Maste 	/* make sure that we don't write data at the beginning */
814*c43e99fdSEd Maste 	evbuffer_prepend(src, "aaaaa", 5);
815*c43e99fdSEd Maste 	evbuffer_validate(src);
816*c43e99fdSEd Maste 	evbuffer_drain(src, 5);
817*c43e99fdSEd Maste 
818*c43e99fdSEd Maste 	tt_assert(evbuffer_remove(src, ((char*)(v[0].iov_base)) + 10,
819*c43e99fdSEd Maste 		strlen(data) - 10) != -1);
820*c43e99fdSEd Maste 
821*c43e99fdSEd Maste 	v[0].iov_len = strlen(data);
822*c43e99fdSEd Maste 
823*c43e99fdSEd Maste 	evbuffer_commit_space(dst, v, 1);
824*c43e99fdSEd Maste 	evbuffer_validate(src);
825*c43e99fdSEd Maste 	evbuffer_validate(dst);
826*c43e99fdSEd Maste 
827*c43e99fdSEd Maste 	tt_int_op(reference_cb_called, ==, 1);
828*c43e99fdSEd Maste 
829*c43e99fdSEd Maste 	tt_assert(!memcmp(evbuffer_pullup(dst, strlen(data)),
830*c43e99fdSEd Maste 			  data, strlen(data)));
831*c43e99fdSEd Maste 	evbuffer_validate(dst);
832*c43e99fdSEd Maste 
833*c43e99fdSEd Maste  end:
834*c43e99fdSEd Maste 	evbuffer_free(dst);
835*c43e99fdSEd Maste 	evbuffer_free(src);
836*c43e99fdSEd Maste }
837*c43e99fdSEd Maste 
838*c43e99fdSEd Maste static void
839*c43e99fdSEd Maste test_evbuffer_reference2(void *ptr)
840*c43e99fdSEd Maste {
841*c43e99fdSEd Maste 	struct evbuffer *buf;
842*c43e99fdSEd Maste 	static char data[4096];
843*c43e99fdSEd Maste 	int data_len = MIN_BUFFER_SIZE-EVBUFFER_CHAIN_SIZE-10;
844*c43e99fdSEd Maste 	char *str;
845*c43e99fdSEd Maste 	int len;
846*c43e99fdSEd Maste 
847*c43e99fdSEd Maste 	memset(data, 'P', sizeof(data));
848*c43e99fdSEd Maste 	buf = evbuffer_new();
849*c43e99fdSEd Maste 	evbuffer_add(buf, data, data_len);
850*c43e99fdSEd Maste 	evbuffer_validate(buf);
851*c43e99fdSEd Maste 	evbuffer_expand(buf, 100);
852*c43e99fdSEd Maste 	evbuffer_validate(buf);
853*c43e99fdSEd Maste 	evbuffer_add_reference(buf, "2", 1, no_cleanup, NULL);
854*c43e99fdSEd Maste 	evbuffer_validate(buf);
855*c43e99fdSEd Maste 	evbuffer_add_printf(buf, "3");
856*c43e99fdSEd Maste 	evbuffer_validate(buf);
857*c43e99fdSEd Maste 
858*c43e99fdSEd Maste 	len = evbuffer_get_length(buf);
859*c43e99fdSEd Maste 	tt_assert(len == data_len+2);
860*c43e99fdSEd Maste 	str = (char *)evbuffer_pullup(buf, -1);
861*c43e99fdSEd Maste 	tt_assert(str[len-3] == 'P');
862*c43e99fdSEd Maste 	tt_assert(str[len-2] == '2');
863*c43e99fdSEd Maste 	tt_assert(str[len-1] == '3');
864*c43e99fdSEd Maste end:
865*c43e99fdSEd Maste 	evbuffer_free(buf);
866*c43e99fdSEd Maste }
867*c43e99fdSEd Maste 
868*c43e99fdSEd Maste static struct event_base *addfile_test_event_base;
869*c43e99fdSEd Maste static int addfile_test_done_writing;
870*c43e99fdSEd Maste static int addfile_test_total_written;
871*c43e99fdSEd Maste static int addfile_test_total_read;
872*c43e99fdSEd Maste 
873*c43e99fdSEd Maste static void
874*c43e99fdSEd Maste addfile_test_writecb(evutil_socket_t fd, short what, void *arg)
875*c43e99fdSEd Maste {
876*c43e99fdSEd Maste 	struct evbuffer *b = arg;
877*c43e99fdSEd Maste 	int r;
878*c43e99fdSEd Maste 	evbuffer_validate(b);
879*c43e99fdSEd Maste 	while (evbuffer_get_length(b)) {
880*c43e99fdSEd Maste 		r = evbuffer_write(b, fd);
881*c43e99fdSEd Maste 		if (r > 0) {
882*c43e99fdSEd Maste 			addfile_test_total_written += r;
883*c43e99fdSEd Maste 			TT_BLATHER(("Wrote %d/%d bytes", r, addfile_test_total_written));
884*c43e99fdSEd Maste 		} else {
885*c43e99fdSEd Maste 			int e = evutil_socket_geterror(fd);
886*c43e99fdSEd Maste 			if (EVUTIL_ERR_RW_RETRIABLE(e))
887*c43e99fdSEd Maste 				return;
888*c43e99fdSEd Maste 			tt_fail_perror("write");
889*c43e99fdSEd Maste 			event_base_loopexit(addfile_test_event_base,NULL);
890*c43e99fdSEd Maste 		}
891*c43e99fdSEd Maste 		evbuffer_validate(b);
892*c43e99fdSEd Maste 	}
893*c43e99fdSEd Maste 	addfile_test_done_writing = 1;
894*c43e99fdSEd Maste 	return;
895*c43e99fdSEd Maste end:
896*c43e99fdSEd Maste 	event_base_loopexit(addfile_test_event_base,NULL);
897*c43e99fdSEd Maste }
898*c43e99fdSEd Maste 
899*c43e99fdSEd Maste static void
900*c43e99fdSEd Maste addfile_test_readcb(evutil_socket_t fd, short what, void *arg)
901*c43e99fdSEd Maste {
902*c43e99fdSEd Maste 	struct evbuffer *b = arg;
903*c43e99fdSEd Maste 	int e, r = 0;
904*c43e99fdSEd Maste 	do {
905*c43e99fdSEd Maste 		r = evbuffer_read(b, fd, 1024);
906*c43e99fdSEd Maste 		if (r > 0) {
907*c43e99fdSEd Maste 			addfile_test_total_read += r;
908*c43e99fdSEd Maste 			TT_BLATHER(("Read %d/%d bytes", r, addfile_test_total_read));
909*c43e99fdSEd Maste 		}
910*c43e99fdSEd Maste 	} while (r > 0);
911*c43e99fdSEd Maste 	if (r < 0) {
912*c43e99fdSEd Maste 		e = evutil_socket_geterror(fd);
913*c43e99fdSEd Maste 		if (! EVUTIL_ERR_RW_RETRIABLE(e)) {
914*c43e99fdSEd Maste 			tt_fail_perror("read");
915*c43e99fdSEd Maste 			event_base_loopexit(addfile_test_event_base,NULL);
916*c43e99fdSEd Maste 		}
917*c43e99fdSEd Maste 	}
918*c43e99fdSEd Maste 	if (addfile_test_done_writing &&
919*c43e99fdSEd Maste 	    addfile_test_total_read >= addfile_test_total_written) {
920*c43e99fdSEd Maste 		event_base_loopexit(addfile_test_event_base,NULL);
921*c43e99fdSEd Maste 	}
922*c43e99fdSEd Maste }
923*c43e99fdSEd Maste 
924*c43e99fdSEd Maste static void
925*c43e99fdSEd Maste test_evbuffer_add_file(void *ptr)
926*c43e99fdSEd Maste {
927*c43e99fdSEd Maste 	struct basic_test_data *testdata = ptr;
928*c43e99fdSEd Maste 	const char *impl = testdata->setup_data;
929*c43e99fdSEd Maste 	struct evbuffer *src = evbuffer_new(), *dest = evbuffer_new();
930*c43e99fdSEd Maste 	char *tmpfilename = NULL;
931*c43e99fdSEd Maste 	char *data = NULL;
932*c43e99fdSEd Maste 	const char *expect_data;
933*c43e99fdSEd Maste 	size_t datalen, expect_len;
934*c43e99fdSEd Maste 	const char *compare;
935*c43e99fdSEd Maste 	int fd = -1;
936*c43e99fdSEd Maste 	int want_ismapping = -1, want_cansendfile = -1;
937*c43e99fdSEd Maste 	unsigned flags = 0;
938*c43e99fdSEd Maste 	int use_segment = 1, use_bigfile = 0, map_from_offset = 0,
939*c43e99fdSEd Maste 	    view_from_offset = 0;
940*c43e99fdSEd Maste 	struct evbuffer_file_segment *seg = NULL;
941*c43e99fdSEd Maste 	ev_off_t starting_offset = 0, mapping_len = -1;
942*c43e99fdSEd Maste 	ev_off_t segment_offset = 0, segment_len = -1;
943*c43e99fdSEd Maste 	struct event *rev=NULL, *wev=NULL;
944*c43e99fdSEd Maste 	struct event_base *base = testdata->base;
945*c43e99fdSEd Maste 	evutil_socket_t pair[2] = {-1, -1};
946*c43e99fdSEd Maste 	struct evutil_weakrand_state seed = { 123456789U };
947*c43e99fdSEd Maste 
948*c43e99fdSEd Maste 	/* This test is highly parameterized based on substrings of its
949*c43e99fdSEd Maste 	 * argument.  The strings are: */
950*c43e99fdSEd Maste 	tt_assert(impl);
951*c43e99fdSEd Maste 	if (strstr(impl, "nosegment")) {
952*c43e99fdSEd Maste 		/* If nosegment is set, use the older evbuffer_add_file
953*c43e99fdSEd Maste 		 * interface */
954*c43e99fdSEd Maste 		use_segment = 0;
955*c43e99fdSEd Maste 	}
956*c43e99fdSEd Maste 	if (strstr(impl, "bigfile")) {
957*c43e99fdSEd Maste 		/* If bigfile is set, use a 512K file.  Else use a smaller
958*c43e99fdSEd Maste 		 * one. */
959*c43e99fdSEd Maste 		use_bigfile = 1;
960*c43e99fdSEd Maste 	}
961*c43e99fdSEd Maste 	if (strstr(impl, "map_offset")) {
962*c43e99fdSEd Maste 		/* If map_offset is set, we build the file segment starting
963*c43e99fdSEd Maste 		 * from a point other than byte 0 and ending somewhere other
964*c43e99fdSEd Maste 		 * than the last byte.  Otherwise we map the whole thing */
965*c43e99fdSEd Maste 		map_from_offset = 1;
966*c43e99fdSEd Maste 	}
967*c43e99fdSEd Maste 	if (strstr(impl, "offset_in_segment")) {
968*c43e99fdSEd Maste 		/* If offset_in_segment is set, we add a subsection of the
969*c43e99fdSEd Maste 		 * file semgment starting from a point other than byte 0 of
970*c43e99fdSEd Maste 		 * the segment. */
971*c43e99fdSEd Maste 		view_from_offset = 1;
972*c43e99fdSEd Maste 	}
973*c43e99fdSEd Maste 	if (strstr(impl, "sendfile")) {
974*c43e99fdSEd Maste 		/* If sendfile is set, we try to use a sendfile/splice style
975*c43e99fdSEd Maste 		 * backend. */
976*c43e99fdSEd Maste 		flags = EVBUF_FS_DISABLE_MMAP;
977*c43e99fdSEd Maste 		want_cansendfile = 1;
978*c43e99fdSEd Maste 		want_ismapping = 0;
979*c43e99fdSEd Maste 	} else if (strstr(impl, "mmap")) {
980*c43e99fdSEd Maste 		/* If sendfile is set, we try to use a mmap/CreateFileMapping
981*c43e99fdSEd Maste 		 * style backend. */
982*c43e99fdSEd Maste 		flags = EVBUF_FS_DISABLE_SENDFILE;
983*c43e99fdSEd Maste 		want_ismapping = 1;
984*c43e99fdSEd Maste 		want_cansendfile = 0;
985*c43e99fdSEd Maste 	} else if (strstr(impl, "linear")) {
986*c43e99fdSEd Maste 		/* If linear is set, we try to use a read-the-whole-thing
987*c43e99fdSEd Maste 		 * backend. */
988*c43e99fdSEd Maste 		flags = EVBUF_FS_DISABLE_SENDFILE|EVBUF_FS_DISABLE_MMAP;
989*c43e99fdSEd Maste 		want_ismapping = 0;
990*c43e99fdSEd Maste 		want_cansendfile = 0;
991*c43e99fdSEd Maste 	} else if (strstr(impl, "default")) {
992*c43e99fdSEd Maste 		/* The caller doesn't care which backend we use. */
993*c43e99fdSEd Maste 		;
994*c43e99fdSEd Maste 	} else {
995*c43e99fdSEd Maste 		/* The caller must choose a backend. */
996*c43e99fdSEd Maste 		TT_DIE(("Didn't recognize the implementation"));
997*c43e99fdSEd Maste 	}
998*c43e99fdSEd Maste 
999*c43e99fdSEd Maste 	if (use_bigfile) {
1000*c43e99fdSEd Maste 		unsigned int i;
1001*c43e99fdSEd Maste 		datalen = 1024*512;
1002*c43e99fdSEd Maste 		data = malloc(1024*512);
1003*c43e99fdSEd Maste 		tt_assert(data);
1004*c43e99fdSEd Maste 		for (i = 0; i < datalen; ++i)
1005*c43e99fdSEd Maste 			data[i] = (char)evutil_weakrand_(&seed);
1006*c43e99fdSEd Maste 	} else {
1007*c43e99fdSEd Maste 		data = strdup("here is a relatively small string.");
1008*c43e99fdSEd Maste 		tt_assert(data);
1009*c43e99fdSEd Maste 		datalen = strlen(data);
1010*c43e99fdSEd Maste 	}
1011*c43e99fdSEd Maste 
1012*c43e99fdSEd Maste 	fd = regress_make_tmpfile(data, datalen, &tmpfilename);
1013*c43e99fdSEd Maste 
1014*c43e99fdSEd Maste 	if (map_from_offset) {
1015*c43e99fdSEd Maste 		starting_offset = datalen/4 + 1;
1016*c43e99fdSEd Maste 		mapping_len = datalen / 2 - 1;
1017*c43e99fdSEd Maste 		expect_data = data + starting_offset;
1018*c43e99fdSEd Maste 		expect_len = mapping_len;
1019*c43e99fdSEd Maste 	} else {
1020*c43e99fdSEd Maste 		expect_data = data;
1021*c43e99fdSEd Maste 		expect_len = datalen;
1022*c43e99fdSEd Maste 	}
1023*c43e99fdSEd Maste 	if (view_from_offset) {
1024*c43e99fdSEd Maste 		tt_assert(use_segment); /* Can't do this with add_file*/
1025*c43e99fdSEd Maste 		segment_offset = expect_len / 3;
1026*c43e99fdSEd Maste 		segment_len = expect_len / 2;
1027*c43e99fdSEd Maste 		expect_data = expect_data + segment_offset;
1028*c43e99fdSEd Maste 		expect_len = segment_len;
1029*c43e99fdSEd Maste 	}
1030*c43e99fdSEd Maste 
1031*c43e99fdSEd Maste 	if (use_segment) {
1032*c43e99fdSEd Maste 		seg = evbuffer_file_segment_new(fd, starting_offset,
1033*c43e99fdSEd Maste 		    mapping_len, flags);
1034*c43e99fdSEd Maste 		tt_assert(seg);
1035*c43e99fdSEd Maste 		if (want_ismapping >= 0) {
1036*c43e99fdSEd Maste 			if (seg->is_mapping != (unsigned)want_ismapping)
1037*c43e99fdSEd Maste 				tt_skip();
1038*c43e99fdSEd Maste 		}
1039*c43e99fdSEd Maste 		if (want_cansendfile >= 0) {
1040*c43e99fdSEd Maste 			if (seg->can_sendfile != (unsigned)want_cansendfile)
1041*c43e99fdSEd Maste 				tt_skip();
1042*c43e99fdSEd Maste 		}
1043*c43e99fdSEd Maste 	}
1044*c43e99fdSEd Maste 
1045*c43e99fdSEd Maste 	/* Say that it drains to a fd so that we can use sendfile. */
1046*c43e99fdSEd Maste 	evbuffer_set_flags(src, EVBUFFER_FLAG_DRAINS_TO_FD);
1047*c43e99fdSEd Maste 
1048*c43e99fdSEd Maste #if defined(EVENT__HAVE_SENDFILE) && defined(__sun__) && defined(__svr4__)
1049*c43e99fdSEd Maste 	/* We need to use a pair of AF_INET sockets, since Solaris
1050*c43e99fdSEd Maste 	   doesn't support sendfile() over AF_UNIX. */
1051*c43e99fdSEd Maste 	if (evutil_ersatz_socketpair_(AF_INET, SOCK_STREAM, 0, pair) == -1)
1052*c43e99fdSEd Maste 		tt_abort_msg("ersatz_socketpair failed");
1053*c43e99fdSEd Maste #else
1054*c43e99fdSEd Maste 	if (evutil_socketpair(AF_UNIX, SOCK_STREAM, 0, pair) == -1)
1055*c43e99fdSEd Maste 		tt_abort_msg("socketpair failed");
1056*c43e99fdSEd Maste #endif
1057*c43e99fdSEd Maste 	evutil_make_socket_nonblocking(pair[0]);
1058*c43e99fdSEd Maste 	evutil_make_socket_nonblocking(pair[1]);
1059*c43e99fdSEd Maste 
1060*c43e99fdSEd Maste 	tt_assert(fd != -1);
1061*c43e99fdSEd Maste 
1062*c43e99fdSEd Maste 	if (use_segment) {
1063*c43e99fdSEd Maste 		tt_assert(evbuffer_add_file_segment(src, seg,
1064*c43e99fdSEd Maste 			segment_offset, segment_len)!=-1);
1065*c43e99fdSEd Maste 	} else {
1066*c43e99fdSEd Maste 		tt_assert(evbuffer_add_file(src, fd, starting_offset,
1067*c43e99fdSEd Maste 			mapping_len) != -1);
1068*c43e99fdSEd Maste 	}
1069*c43e99fdSEd Maste 
1070*c43e99fdSEd Maste 	evbuffer_validate(src);
1071*c43e99fdSEd Maste 
1072*c43e99fdSEd Maste 	addfile_test_event_base = base;
1073*c43e99fdSEd Maste 	addfile_test_done_writing = 0;
1074*c43e99fdSEd Maste 	addfile_test_total_written = 0;
1075*c43e99fdSEd Maste 	addfile_test_total_read = 0;
1076*c43e99fdSEd Maste 
1077*c43e99fdSEd Maste 	wev = event_new(base, pair[0], EV_WRITE|EV_PERSIST,
1078*c43e99fdSEd Maste 	    addfile_test_writecb, src);
1079*c43e99fdSEd Maste 	rev = event_new(base, pair[1], EV_READ|EV_PERSIST,
1080*c43e99fdSEd Maste 	    addfile_test_readcb, dest);
1081*c43e99fdSEd Maste 
1082*c43e99fdSEd Maste 	event_add(wev, NULL);
1083*c43e99fdSEd Maste 	event_add(rev, NULL);
1084*c43e99fdSEd Maste 	event_base_dispatch(base);
1085*c43e99fdSEd Maste 
1086*c43e99fdSEd Maste 	evbuffer_validate(src);
1087*c43e99fdSEd Maste 	evbuffer_validate(dest);
1088*c43e99fdSEd Maste 
1089*c43e99fdSEd Maste 	tt_assert(addfile_test_done_writing);
1090*c43e99fdSEd Maste 	tt_int_op(addfile_test_total_written, ==, expect_len);
1091*c43e99fdSEd Maste 	tt_int_op(addfile_test_total_read, ==, expect_len);
1092*c43e99fdSEd Maste 
1093*c43e99fdSEd Maste 	compare = (char *)evbuffer_pullup(dest, expect_len);
1094*c43e99fdSEd Maste 	tt_assert(compare != NULL);
1095*c43e99fdSEd Maste 	if (memcmp(compare, expect_data, expect_len)) {
1096*c43e99fdSEd Maste 		tt_abort_msg("Data from add_file differs.");
1097*c43e99fdSEd Maste 	}
1098*c43e99fdSEd Maste 
1099*c43e99fdSEd Maste 	evbuffer_validate(dest);
1100*c43e99fdSEd Maste  end:
1101*c43e99fdSEd Maste 	if (data)
1102*c43e99fdSEd Maste 		free(data);
1103*c43e99fdSEd Maste 	if (seg)
1104*c43e99fdSEd Maste 		evbuffer_file_segment_free(seg);
1105*c43e99fdSEd Maste 	if (src)
1106*c43e99fdSEd Maste 		evbuffer_free(src);
1107*c43e99fdSEd Maste 	if (dest)
1108*c43e99fdSEd Maste 		evbuffer_free(dest);
1109*c43e99fdSEd Maste 	if (pair[0] >= 0)
1110*c43e99fdSEd Maste 		evutil_closesocket(pair[0]);
1111*c43e99fdSEd Maste 	if (pair[1] >= 0)
1112*c43e99fdSEd Maste 		evutil_closesocket(pair[1]);
1113*c43e99fdSEd Maste 	if (wev)
1114*c43e99fdSEd Maste 		event_free(wev);
1115*c43e99fdSEd Maste 	if (rev)
1116*c43e99fdSEd Maste 		event_free(rev);
1117*c43e99fdSEd Maste 	if (tmpfilename) {
1118*c43e99fdSEd Maste 		unlink(tmpfilename);
1119*c43e99fdSEd Maste 		free(tmpfilename);
1120*c43e99fdSEd Maste 	}
1121*c43e99fdSEd Maste }
1122*c43e99fdSEd Maste 
1123*c43e99fdSEd Maste static int file_segment_cleanup_cb_called_count = 0;
1124*c43e99fdSEd Maste static struct evbuffer_file_segment const* file_segment_cleanup_cb_called_with = NULL;
1125*c43e99fdSEd Maste static int file_segment_cleanup_cb_called_with_flags = 0;
1126*c43e99fdSEd Maste static void* file_segment_cleanup_cb_called_with_arg = NULL;
1127*c43e99fdSEd Maste static void
1128*c43e99fdSEd Maste file_segment_cleanup_cp(struct evbuffer_file_segment const* seg, int flags, void* arg)
1129*c43e99fdSEd Maste {
1130*c43e99fdSEd Maste 	++file_segment_cleanup_cb_called_count;
1131*c43e99fdSEd Maste 	file_segment_cleanup_cb_called_with = seg;
1132*c43e99fdSEd Maste 	file_segment_cleanup_cb_called_with_flags = flags;
1133*c43e99fdSEd Maste 	file_segment_cleanup_cb_called_with_arg = arg;
1134*c43e99fdSEd Maste }
1135*c43e99fdSEd Maste 
1136*c43e99fdSEd Maste static void
1137*c43e99fdSEd Maste test_evbuffer_file_segment_add_cleanup_cb(void* ptr)
1138*c43e99fdSEd Maste {
1139*c43e99fdSEd Maste 	char *tmpfilename = NULL;
1140*c43e99fdSEd Maste 	int fd = -1;
1141*c43e99fdSEd Maste 	struct evbuffer *evb = NULL;
1142*c43e99fdSEd Maste 	struct evbuffer_file_segment *seg = NULL, *segptr;
1143*c43e99fdSEd Maste 	char const* arg = "token";
1144*c43e99fdSEd Maste 
1145*c43e99fdSEd Maste 	fd = regress_make_tmpfile("file_segment_test_file", 22, &tmpfilename);
1146*c43e99fdSEd Maste 	tt_int_op(fd, >=, 0);
1147*c43e99fdSEd Maste 
1148*c43e99fdSEd Maste 	evb = evbuffer_new();
1149*c43e99fdSEd Maste 	tt_assert(evb);
1150*c43e99fdSEd Maste 
1151*c43e99fdSEd Maste 	segptr = seg = evbuffer_file_segment_new(fd, 0, -1, 0);
1152*c43e99fdSEd Maste 	tt_assert(seg);
1153*c43e99fdSEd Maste 
1154*c43e99fdSEd Maste 	evbuffer_file_segment_add_cleanup_cb(
1155*c43e99fdSEd Maste 	  seg, &file_segment_cleanup_cp, (void*)arg);
1156*c43e99fdSEd Maste 
1157*c43e99fdSEd Maste 	tt_assert(fd != -1);
1158*c43e99fdSEd Maste 
1159*c43e99fdSEd Maste 	tt_assert(evbuffer_add_file_segment(evb, seg, 0, -1)!=-1);
1160*c43e99fdSEd Maste 
1161*c43e99fdSEd Maste 	evbuffer_validate(evb);
1162*c43e99fdSEd Maste 
1163*c43e99fdSEd Maste 	tt_int_op(file_segment_cleanup_cb_called_count, ==, 0);
1164*c43e99fdSEd Maste 	evbuffer_file_segment_free(seg);
1165*c43e99fdSEd Maste 	seg = NULL; /* Prevent double-free. */
1166*c43e99fdSEd Maste 
1167*c43e99fdSEd Maste 	tt_int_op(file_segment_cleanup_cb_called_count, ==, 0);
1168*c43e99fdSEd Maste 	evbuffer_free(evb);
1169*c43e99fdSEd Maste 	evb = NULL; /* pevent double-free */
1170*c43e99fdSEd Maste 
1171*c43e99fdSEd Maste 	tt_int_op(file_segment_cleanup_cb_called_count, ==, 1);
1172*c43e99fdSEd Maste 	tt_assert(file_segment_cleanup_cb_called_with == segptr);
1173*c43e99fdSEd Maste 	tt_assert(file_segment_cleanup_cb_called_with_flags == 0);
1174*c43e99fdSEd Maste 	tt_assert(file_segment_cleanup_cb_called_with_arg == (void*)arg);
1175*c43e99fdSEd Maste 
1176*c43e99fdSEd Maste end:
1177*c43e99fdSEd Maste 	if (evb)
1178*c43e99fdSEd Maste 		evbuffer_free(evb);
1179*c43e99fdSEd Maste 	if (seg)
1180*c43e99fdSEd Maste 		evbuffer_file_segment_free(seg);
1181*c43e99fdSEd Maste 	if (tmpfilename) {
1182*c43e99fdSEd Maste 		unlink(tmpfilename);
1183*c43e99fdSEd Maste 		free(tmpfilename);
1184*c43e99fdSEd Maste 	}
1185*c43e99fdSEd Maste }
1186*c43e99fdSEd Maste 
1187*c43e99fdSEd Maste #ifndef EVENT__DISABLE_MM_REPLACEMENT
1188*c43e99fdSEd Maste static void *
1189*c43e99fdSEd Maste failing_malloc(size_t how_much)
1190*c43e99fdSEd Maste {
1191*c43e99fdSEd Maste 	errno = ENOMEM;
1192*c43e99fdSEd Maste 	return NULL;
1193*c43e99fdSEd Maste }
1194*c43e99fdSEd Maste #endif
1195*c43e99fdSEd Maste 
1196*c43e99fdSEd Maste static void
1197*c43e99fdSEd Maste test_evbuffer_readln(void *ptr)
1198*c43e99fdSEd Maste {
1199*c43e99fdSEd Maste 	struct evbuffer *evb = evbuffer_new();
1200*c43e99fdSEd Maste 	struct evbuffer *evb_tmp = evbuffer_new();
1201*c43e99fdSEd Maste 	const char *s;
1202*c43e99fdSEd Maste 	char *cp = NULL;
1203*c43e99fdSEd Maste 	size_t sz;
1204*c43e99fdSEd Maste 
1205*c43e99fdSEd Maste #define tt_line_eq(content)						\
1206*c43e99fdSEd Maste 	TT_STMT_BEGIN							\
1207*c43e99fdSEd Maste 	if (!cp || sz != strlen(content) || strcmp(cp, content)) {	\
1208*c43e99fdSEd Maste 		TT_DIE(("Wanted %s; got %s [%d]", content, cp, (int)sz)); \
1209*c43e99fdSEd Maste 	}								\
1210*c43e99fdSEd Maste 	TT_STMT_END
1211*c43e99fdSEd Maste 
1212*c43e99fdSEd Maste 	/* Test EOL_ANY. */
1213*c43e99fdSEd Maste 	s = "complex silly newline\r\n\n\r\n\n\rmore\0\n";
1214*c43e99fdSEd Maste 	evbuffer_add(evb, s, strlen(s)+2);
1215*c43e99fdSEd Maste 	evbuffer_validate(evb);
1216*c43e99fdSEd Maste 	cp = evbuffer_readln(evb, &sz, EVBUFFER_EOL_ANY);
1217*c43e99fdSEd Maste 	tt_line_eq("complex silly newline");
1218*c43e99fdSEd Maste 	free(cp);
1219*c43e99fdSEd Maste 	evbuffer_validate(evb);
1220*c43e99fdSEd Maste 	cp = evbuffer_readln(evb, &sz, EVBUFFER_EOL_ANY);
1221*c43e99fdSEd Maste 	if (!cp || sz != 5 || memcmp(cp, "more\0\0", 6))
1222*c43e99fdSEd Maste 		tt_abort_msg("Not as expected");
1223*c43e99fdSEd Maste 	tt_uint_op(evbuffer_get_length(evb), ==, 0);
1224*c43e99fdSEd Maste 	evbuffer_validate(evb);
1225*c43e99fdSEd Maste 	s = "\nno newline";
1226*c43e99fdSEd Maste 	evbuffer_add(evb, s, strlen(s));
1227*c43e99fdSEd Maste 	free(cp);
1228*c43e99fdSEd Maste 	evbuffer_validate(evb);
1229*c43e99fdSEd Maste 	cp = evbuffer_readln(evb, &sz, EVBUFFER_EOL_ANY);
1230*c43e99fdSEd Maste 	tt_line_eq("");
1231*c43e99fdSEd Maste 	free(cp);
1232*c43e99fdSEd Maste 	evbuffer_validate(evb);
1233*c43e99fdSEd Maste 	cp = evbuffer_readln(evb, &sz, EVBUFFER_EOL_ANY);
1234*c43e99fdSEd Maste 	tt_assert(!cp);
1235*c43e99fdSEd Maste 	evbuffer_validate(evb);
1236*c43e99fdSEd Maste 	evbuffer_drain(evb, evbuffer_get_length(evb));
1237*c43e99fdSEd Maste 	tt_assert(evbuffer_get_length(evb) == 0);
1238*c43e99fdSEd Maste 	evbuffer_validate(evb);
1239*c43e99fdSEd Maste 
1240*c43e99fdSEd Maste 	/* Test EOL_CRLF */
1241*c43e99fdSEd Maste 	s = "Line with\rin the middle\nLine with good crlf\r\n\nfinal\n";
1242*c43e99fdSEd Maste 	evbuffer_add(evb, s, strlen(s));
1243*c43e99fdSEd Maste 	evbuffer_validate(evb);
1244*c43e99fdSEd Maste 	cp = evbuffer_readln(evb, &sz, EVBUFFER_EOL_CRLF);
1245*c43e99fdSEd Maste 	tt_line_eq("Line with\rin the middle");
1246*c43e99fdSEd Maste 	free(cp);
1247*c43e99fdSEd Maste 	evbuffer_validate(evb);
1248*c43e99fdSEd Maste 
1249*c43e99fdSEd Maste 	cp = evbuffer_readln(evb, &sz, EVBUFFER_EOL_CRLF);
1250*c43e99fdSEd Maste 	tt_line_eq("Line with good crlf");
1251*c43e99fdSEd Maste 	free(cp);
1252*c43e99fdSEd Maste 	evbuffer_validate(evb);
1253*c43e99fdSEd Maste 
1254*c43e99fdSEd Maste 	cp = evbuffer_readln(evb, &sz, EVBUFFER_EOL_CRLF);
1255*c43e99fdSEd Maste 	tt_line_eq("");
1256*c43e99fdSEd Maste 	free(cp);
1257*c43e99fdSEd Maste 	evbuffer_validate(evb);
1258*c43e99fdSEd Maste 
1259*c43e99fdSEd Maste 	cp = evbuffer_readln(evb, &sz, EVBUFFER_EOL_CRLF);
1260*c43e99fdSEd Maste 	tt_line_eq("final");
1261*c43e99fdSEd Maste 	s = "x";
1262*c43e99fdSEd Maste 	evbuffer_validate(evb);
1263*c43e99fdSEd Maste 	evbuffer_add(evb, s, 1);
1264*c43e99fdSEd Maste 	evbuffer_validate(evb);
1265*c43e99fdSEd Maste 	free(cp);
1266*c43e99fdSEd Maste 	cp = evbuffer_readln(evb, &sz, EVBUFFER_EOL_CRLF);
1267*c43e99fdSEd Maste 	tt_assert(!cp);
1268*c43e99fdSEd Maste 	evbuffer_validate(evb);
1269*c43e99fdSEd Maste 
1270*c43e99fdSEd Maste 	/* Test CRLF_STRICT */
1271*c43e99fdSEd Maste 	s = " and a bad crlf\nand a good one\r\n\r\nMore\r";
1272*c43e99fdSEd Maste 	evbuffer_add(evb, s, strlen(s));
1273*c43e99fdSEd Maste 	evbuffer_validate(evb);
1274*c43e99fdSEd Maste 	cp = evbuffer_readln(evb, &sz, EVBUFFER_EOL_CRLF_STRICT);
1275*c43e99fdSEd Maste 	tt_line_eq("x and a bad crlf\nand a good one");
1276*c43e99fdSEd Maste 	free(cp);
1277*c43e99fdSEd Maste 	evbuffer_validate(evb);
1278*c43e99fdSEd Maste 
1279*c43e99fdSEd Maste 	cp = evbuffer_readln(evb, &sz, EVBUFFER_EOL_CRLF_STRICT);
1280*c43e99fdSEd Maste 	tt_line_eq("");
1281*c43e99fdSEd Maste 	free(cp);
1282*c43e99fdSEd Maste 	evbuffer_validate(evb);
1283*c43e99fdSEd Maste 
1284*c43e99fdSEd Maste 	cp = evbuffer_readln(evb, &sz, EVBUFFER_EOL_CRLF_STRICT);
1285*c43e99fdSEd Maste 	tt_assert(!cp);
1286*c43e99fdSEd Maste 	evbuffer_validate(evb);
1287*c43e99fdSEd Maste 	evbuffer_add(evb, "\n", 1);
1288*c43e99fdSEd Maste 	evbuffer_validate(evb);
1289*c43e99fdSEd Maste 
1290*c43e99fdSEd Maste 	cp = evbuffer_readln(evb, &sz, EVBUFFER_EOL_CRLF_STRICT);
1291*c43e99fdSEd Maste 	tt_line_eq("More");
1292*c43e99fdSEd Maste 	free(cp);
1293*c43e99fdSEd Maste 	tt_assert(evbuffer_get_length(evb) == 0);
1294*c43e99fdSEd Maste 	evbuffer_validate(evb);
1295*c43e99fdSEd Maste 
1296*c43e99fdSEd Maste 	s = "An internal CR\r is not an eol\r\nNor is a lack of one";
1297*c43e99fdSEd Maste 	evbuffer_add(evb, s, strlen(s));
1298*c43e99fdSEd Maste 	cp = evbuffer_readln(evb, &sz, EVBUFFER_EOL_CRLF_STRICT);
1299*c43e99fdSEd Maste 	tt_line_eq("An internal CR\r is not an eol");
1300*c43e99fdSEd Maste 	free(cp);
1301*c43e99fdSEd Maste 	evbuffer_validate(evb);
1302*c43e99fdSEd Maste 
1303*c43e99fdSEd Maste 	cp = evbuffer_readln(evb, &sz, EVBUFFER_EOL_CRLF_STRICT);
1304*c43e99fdSEd Maste 	tt_assert(!cp);
1305*c43e99fdSEd Maste 	evbuffer_validate(evb);
1306*c43e99fdSEd Maste 
1307*c43e99fdSEd Maste 	evbuffer_add(evb, "\r\n", 2);
1308*c43e99fdSEd Maste 	evbuffer_validate(evb);
1309*c43e99fdSEd Maste 	cp = evbuffer_readln(evb, &sz, EVBUFFER_EOL_CRLF_STRICT);
1310*c43e99fdSEd Maste 	tt_line_eq("Nor is a lack of one");
1311*c43e99fdSEd Maste 	free(cp);
1312*c43e99fdSEd Maste 	tt_assert(evbuffer_get_length(evb) == 0);
1313*c43e99fdSEd Maste 	evbuffer_validate(evb);
1314*c43e99fdSEd Maste 
1315*c43e99fdSEd Maste 	/* Test LF */
1316*c43e99fdSEd Maste 	s = "An\rand a nl\n\nText";
1317*c43e99fdSEd Maste 	evbuffer_add(evb, s, strlen(s));
1318*c43e99fdSEd Maste 	evbuffer_validate(evb);
1319*c43e99fdSEd Maste 
1320*c43e99fdSEd Maste 	cp = evbuffer_readln(evb, &sz, EVBUFFER_EOL_LF);
1321*c43e99fdSEd Maste 	tt_line_eq("An\rand a nl");
1322*c43e99fdSEd Maste 	free(cp);
1323*c43e99fdSEd Maste 	evbuffer_validate(evb);
1324*c43e99fdSEd Maste 
1325*c43e99fdSEd Maste 	cp = evbuffer_readln(evb, &sz, EVBUFFER_EOL_LF);
1326*c43e99fdSEd Maste 	tt_line_eq("");
1327*c43e99fdSEd Maste 	free(cp);
1328*c43e99fdSEd Maste 	evbuffer_validate(evb);
1329*c43e99fdSEd Maste 
1330*c43e99fdSEd Maste 	cp = evbuffer_readln(evb, &sz, EVBUFFER_EOL_LF);
1331*c43e99fdSEd Maste 	tt_assert(!cp);
1332*c43e99fdSEd Maste 	free(cp);
1333*c43e99fdSEd Maste 	evbuffer_add(evb, "\n", 1);
1334*c43e99fdSEd Maste 	evbuffer_validate(evb);
1335*c43e99fdSEd Maste 	cp = evbuffer_readln(evb, &sz, EVBUFFER_EOL_LF);
1336*c43e99fdSEd Maste 	tt_line_eq("Text");
1337*c43e99fdSEd Maste 	free(cp);
1338*c43e99fdSEd Maste 	evbuffer_validate(evb);
1339*c43e99fdSEd Maste 
1340*c43e99fdSEd Maste 	/* Test NUL */
1341*c43e99fdSEd Maste 	tt_int_op(evbuffer_get_length(evb), ==, 0);
1342*c43e99fdSEd Maste 	{
1343*c43e99fdSEd Maste 		char x[] =
1344*c43e99fdSEd Maste 		    "NUL\n\0\0"
1345*c43e99fdSEd Maste 		    "The all-zeros character which may serve\0"
1346*c43e99fdSEd Maste 		    "to accomplish time fill\0and media fill";
1347*c43e99fdSEd Maste 		/* Add all but the final NUL of x. */
1348*c43e99fdSEd Maste 		evbuffer_add(evb, x, sizeof(x)-1);
1349*c43e99fdSEd Maste 	}
1350*c43e99fdSEd Maste 	cp = evbuffer_readln(evb, &sz, EVBUFFER_EOL_NUL);
1351*c43e99fdSEd Maste 	tt_line_eq("NUL\n");
1352*c43e99fdSEd Maste 	free(cp);
1353*c43e99fdSEd Maste 	cp = evbuffer_readln(evb, &sz, EVBUFFER_EOL_NUL);
1354*c43e99fdSEd Maste 	tt_line_eq("");
1355*c43e99fdSEd Maste 	free(cp);
1356*c43e99fdSEd Maste 	cp = evbuffer_readln(evb, &sz, EVBUFFER_EOL_NUL);
1357*c43e99fdSEd Maste 	tt_line_eq("The all-zeros character which may serve");
1358*c43e99fdSEd Maste 	free(cp);
1359*c43e99fdSEd Maste 	cp = evbuffer_readln(evb, &sz, EVBUFFER_EOL_NUL);
1360*c43e99fdSEd Maste 	tt_line_eq("to accomplish time fill");
1361*c43e99fdSEd Maste 	free(cp);
1362*c43e99fdSEd Maste 	cp = evbuffer_readln(evb, &sz, EVBUFFER_EOL_NUL);
1363*c43e99fdSEd Maste 	tt_ptr_op(cp, ==, NULL);
1364*c43e99fdSEd Maste 	evbuffer_drain(evb, -1);
1365*c43e99fdSEd Maste 
1366*c43e99fdSEd Maste 	/* Test CRLF_STRICT - across boundaries*/
1367*c43e99fdSEd Maste 	s = " and a bad crlf\nand a good one\r";
1368*c43e99fdSEd Maste 	evbuffer_add(evb_tmp, s, strlen(s));
1369*c43e99fdSEd Maste 	evbuffer_validate(evb);
1370*c43e99fdSEd Maste 	evbuffer_add_buffer(evb, evb_tmp);
1371*c43e99fdSEd Maste 	evbuffer_validate(evb);
1372*c43e99fdSEd Maste 	s = "\n\r";
1373*c43e99fdSEd Maste 	evbuffer_add(evb_tmp, s, strlen(s));
1374*c43e99fdSEd Maste 	evbuffer_validate(evb);
1375*c43e99fdSEd Maste 	evbuffer_add_buffer(evb, evb_tmp);
1376*c43e99fdSEd Maste 	evbuffer_validate(evb);
1377*c43e99fdSEd Maste 	s = "\nMore\r";
1378*c43e99fdSEd Maste 	evbuffer_add(evb_tmp, s, strlen(s));
1379*c43e99fdSEd Maste 	evbuffer_validate(evb);
1380*c43e99fdSEd Maste 	evbuffer_add_buffer(evb, evb_tmp);
1381*c43e99fdSEd Maste 	evbuffer_validate(evb);
1382*c43e99fdSEd Maste 
1383*c43e99fdSEd Maste 	cp = evbuffer_readln(evb, &sz, EVBUFFER_EOL_CRLF_STRICT);
1384*c43e99fdSEd Maste 	tt_line_eq(" and a bad crlf\nand a good one");
1385*c43e99fdSEd Maste 	free(cp);
1386*c43e99fdSEd Maste 	evbuffer_validate(evb);
1387*c43e99fdSEd Maste 
1388*c43e99fdSEd Maste 	cp = evbuffer_readln(evb, &sz, EVBUFFER_EOL_CRLF_STRICT);
1389*c43e99fdSEd Maste 	tt_line_eq("");
1390*c43e99fdSEd Maste 	free(cp);
1391*c43e99fdSEd Maste 	evbuffer_validate(evb);
1392*c43e99fdSEd Maste 
1393*c43e99fdSEd Maste 	cp = evbuffer_readln(evb, &sz, EVBUFFER_EOL_CRLF_STRICT);
1394*c43e99fdSEd Maste 	tt_assert(!cp);
1395*c43e99fdSEd Maste 	free(cp);
1396*c43e99fdSEd Maste 	evbuffer_validate(evb);
1397*c43e99fdSEd Maste 	evbuffer_add(evb, "\n", 1);
1398*c43e99fdSEd Maste 	evbuffer_validate(evb);
1399*c43e99fdSEd Maste 	cp = evbuffer_readln(evb, &sz, EVBUFFER_EOL_CRLF_STRICT);
1400*c43e99fdSEd Maste 	tt_line_eq("More");
1401*c43e99fdSEd Maste 	free(cp); cp = NULL;
1402*c43e99fdSEd Maste 	evbuffer_validate(evb);
1403*c43e99fdSEd Maste 	tt_assert(evbuffer_get_length(evb) == 0);
1404*c43e99fdSEd Maste 
1405*c43e99fdSEd Maste 	/* Test memory problem*/
1406*c43e99fdSEd Maste 	s = "one line\ntwo line\nblue line";
1407*c43e99fdSEd Maste 	evbuffer_add(evb_tmp, s, strlen(s));
1408*c43e99fdSEd Maste 	evbuffer_validate(evb);
1409*c43e99fdSEd Maste 	evbuffer_add_buffer(evb, evb_tmp);
1410*c43e99fdSEd Maste 	evbuffer_validate(evb);
1411*c43e99fdSEd Maste 
1412*c43e99fdSEd Maste 	cp = evbuffer_readln(evb, &sz, EVBUFFER_EOL_LF);
1413*c43e99fdSEd Maste 	tt_line_eq("one line");
1414*c43e99fdSEd Maste 	free(cp); cp = NULL;
1415*c43e99fdSEd Maste 	evbuffer_validate(evb);
1416*c43e99fdSEd Maste 
1417*c43e99fdSEd Maste 	/* the next call to readline should fail */
1418*c43e99fdSEd Maste #ifndef EVENT__DISABLE_MM_REPLACEMENT
1419*c43e99fdSEd Maste 	event_set_mem_functions(failing_malloc, realloc, free);
1420*c43e99fdSEd Maste 	cp = evbuffer_readln(evb, &sz, EVBUFFER_EOL_LF);
1421*c43e99fdSEd Maste 	tt_assert(cp == NULL);
1422*c43e99fdSEd Maste 	evbuffer_validate(evb);
1423*c43e99fdSEd Maste 
1424*c43e99fdSEd Maste 	/* now we should get the next line back */
1425*c43e99fdSEd Maste 	event_set_mem_functions(malloc, realloc, free);
1426*c43e99fdSEd Maste #endif
1427*c43e99fdSEd Maste 	cp = evbuffer_readln(evb, &sz, EVBUFFER_EOL_LF);
1428*c43e99fdSEd Maste 	tt_line_eq("two line");
1429*c43e99fdSEd Maste 	free(cp); cp = NULL;
1430*c43e99fdSEd Maste 	evbuffer_validate(evb);
1431*c43e99fdSEd Maste 
1432*c43e99fdSEd Maste  end:
1433*c43e99fdSEd Maste 	evbuffer_free(evb);
1434*c43e99fdSEd Maste 	evbuffer_free(evb_tmp);
1435*c43e99fdSEd Maste 	if (cp) free(cp);
1436*c43e99fdSEd Maste }
1437*c43e99fdSEd Maste 
1438*c43e99fdSEd Maste static void
1439*c43e99fdSEd Maste test_evbuffer_search_eol(void *ptr)
1440*c43e99fdSEd Maste {
1441*c43e99fdSEd Maste 	struct evbuffer *buf = evbuffer_new();
1442*c43e99fdSEd Maste 	struct evbuffer_ptr ptr1, ptr2;
1443*c43e99fdSEd Maste 	const char *s;
1444*c43e99fdSEd Maste 	size_t eol_len;
1445*c43e99fdSEd Maste 
1446*c43e99fdSEd Maste 	s = "string! \r\n\r\nx\n";
1447*c43e99fdSEd Maste 	evbuffer_add(buf, s, strlen(s));
1448*c43e99fdSEd Maste 	eol_len = -1;
1449*c43e99fdSEd Maste 	ptr1 = evbuffer_search_eol(buf, NULL, &eol_len, EVBUFFER_EOL_CRLF);
1450*c43e99fdSEd Maste 	tt_int_op(ptr1.pos, ==, 8);
1451*c43e99fdSEd Maste 	tt_int_op(eol_len, ==, 2);
1452*c43e99fdSEd Maste 
1453*c43e99fdSEd Maste 	eol_len = -1;
1454*c43e99fdSEd Maste 	ptr2 = evbuffer_search_eol(buf, &ptr1, &eol_len, EVBUFFER_EOL_CRLF);
1455*c43e99fdSEd Maste 	tt_int_op(ptr2.pos, ==, 8);
1456*c43e99fdSEd Maste 	tt_int_op(eol_len, ==, 2);
1457*c43e99fdSEd Maste 
1458*c43e99fdSEd Maste 	evbuffer_ptr_set(buf, &ptr1, 1, EVBUFFER_PTR_ADD);
1459*c43e99fdSEd Maste 	eol_len = -1;
1460*c43e99fdSEd Maste 	ptr2 = evbuffer_search_eol(buf, &ptr1, &eol_len, EVBUFFER_EOL_CRLF);
1461*c43e99fdSEd Maste 	tt_int_op(ptr2.pos, ==, 9);
1462*c43e99fdSEd Maste 	tt_int_op(eol_len, ==, 1);
1463*c43e99fdSEd Maste 
1464*c43e99fdSEd Maste 	eol_len = -1;
1465*c43e99fdSEd Maste 	ptr2 = evbuffer_search_eol(buf, &ptr1, &eol_len, EVBUFFER_EOL_CRLF_STRICT);
1466*c43e99fdSEd Maste 	tt_int_op(ptr2.pos, ==, 10);
1467*c43e99fdSEd Maste 	tt_int_op(eol_len, ==, 2);
1468*c43e99fdSEd Maste 
1469*c43e99fdSEd Maste 	eol_len = -1;
1470*c43e99fdSEd Maste 	ptr1 = evbuffer_search_eol(buf, NULL, &eol_len, EVBUFFER_EOL_LF);
1471*c43e99fdSEd Maste 	tt_int_op(ptr1.pos, ==, 9);
1472*c43e99fdSEd Maste 	tt_int_op(eol_len, ==, 1);
1473*c43e99fdSEd Maste 
1474*c43e99fdSEd Maste 	eol_len = -1;
1475*c43e99fdSEd Maste 	ptr2 = evbuffer_search_eol(buf, &ptr1, &eol_len, EVBUFFER_EOL_LF);
1476*c43e99fdSEd Maste 	tt_int_op(ptr2.pos, ==, 9);
1477*c43e99fdSEd Maste 	tt_int_op(eol_len, ==, 1);
1478*c43e99fdSEd Maste 
1479*c43e99fdSEd Maste 	evbuffer_ptr_set(buf, &ptr1, 1, EVBUFFER_PTR_ADD);
1480*c43e99fdSEd Maste 	eol_len = -1;
1481*c43e99fdSEd Maste 	ptr2 = evbuffer_search_eol(buf, &ptr1, &eol_len, EVBUFFER_EOL_LF);
1482*c43e99fdSEd Maste 	tt_int_op(ptr2.pos, ==, 11);
1483*c43e99fdSEd Maste 	tt_int_op(eol_len, ==, 1);
1484*c43e99fdSEd Maste 
1485*c43e99fdSEd Maste 	tt_assert(evbuffer_ptr_set(buf, &ptr1, evbuffer_get_length(buf), EVBUFFER_PTR_SET) == 0);
1486*c43e99fdSEd Maste 	eol_len = -1;
1487*c43e99fdSEd Maste 	ptr2 = evbuffer_search_eol(buf, &ptr1, &eol_len, EVBUFFER_EOL_LF);
1488*c43e99fdSEd Maste 	tt_int_op(ptr2.pos, ==, -1);
1489*c43e99fdSEd Maste 	tt_int_op(eol_len, ==, 0);
1490*c43e99fdSEd Maste 
1491*c43e99fdSEd Maste end:
1492*c43e99fdSEd Maste 	evbuffer_free(buf);
1493*c43e99fdSEd Maste }
1494*c43e99fdSEd Maste 
1495*c43e99fdSEd Maste static void
1496*c43e99fdSEd Maste test_evbuffer_iterative(void *ptr)
1497*c43e99fdSEd Maste {
1498*c43e99fdSEd Maste 	struct evbuffer *buf = evbuffer_new();
1499*c43e99fdSEd Maste 	const char *abc = "abcdefghijklmnopqrstvuwxyzabcdefghijklmnopqrstvuwxyzabcdefghijklmnopqrstvuwxyzabcdefghijklmnopqrstvuwxyz";
1500*c43e99fdSEd Maste 	unsigned i, j, sum, n;
1501*c43e99fdSEd Maste 
1502*c43e99fdSEd Maste 	sum = 0;
1503*c43e99fdSEd Maste 	n = 0;
1504*c43e99fdSEd Maste 	for (i = 0; i < 1000; ++i) {
1505*c43e99fdSEd Maste 		for (j = 1; j < strlen(abc); ++j) {
1506*c43e99fdSEd Maste 			char format[32];
1507*c43e99fdSEd Maste 			evutil_snprintf(format, sizeof(format), "%%%u.%us", j, j);
1508*c43e99fdSEd Maste 			evbuffer_add_printf(buf, format, abc);
1509*c43e99fdSEd Maste 
1510*c43e99fdSEd Maste 			/* Only check for rep violations every so often.
1511*c43e99fdSEd Maste 			   Walking over the whole list of chains can get
1512*c43e99fdSEd Maste 			   pretty expensive as it gets long.
1513*c43e99fdSEd Maste 			 */
1514*c43e99fdSEd Maste 			if ((n % 337) == 0)
1515*c43e99fdSEd Maste 				evbuffer_validate(buf);
1516*c43e99fdSEd Maste 
1517*c43e99fdSEd Maste 			sum += j;
1518*c43e99fdSEd Maste 			n++;
1519*c43e99fdSEd Maste 		}
1520*c43e99fdSEd Maste 	}
1521*c43e99fdSEd Maste 	evbuffer_validate(buf);
1522*c43e99fdSEd Maste 
1523*c43e99fdSEd Maste 	tt_uint_op(sum, ==, evbuffer_get_length(buf));
1524*c43e99fdSEd Maste 
1525*c43e99fdSEd Maste 	{
1526*c43e99fdSEd Maste 		size_t a,w,u;
1527*c43e99fdSEd Maste 		a=w=u=0;
1528*c43e99fdSEd Maste 		evbuffer_get_waste(buf, &a, &w, &u);
1529*c43e99fdSEd Maste 		if (0)
1530*c43e99fdSEd Maste 			printf("Allocated: %u.\nWasted: %u.\nUsed: %u.",
1531*c43e99fdSEd Maste 			    (unsigned)a, (unsigned)w, (unsigned)u);
1532*c43e99fdSEd Maste 		tt_assert( ((double)w)/a < .125);
1533*c43e99fdSEd Maste 	}
1534*c43e99fdSEd Maste  end:
1535*c43e99fdSEd Maste 	evbuffer_free(buf);
1536*c43e99fdSEd Maste 
1537*c43e99fdSEd Maste }
1538*c43e99fdSEd Maste 
1539*c43e99fdSEd Maste static void
1540*c43e99fdSEd Maste test_evbuffer_find(void *ptr)
1541*c43e99fdSEd Maste {
1542*c43e99fdSEd Maste 	unsigned char* p;
1543*c43e99fdSEd Maste 	const char* test1 = "1234567890\r\n";
1544*c43e99fdSEd Maste 	const char* test2 = "1234567890\r";
1545*c43e99fdSEd Maste #define EVBUFFER_INITIAL_LENGTH 256
1546*c43e99fdSEd Maste 	char test3[EVBUFFER_INITIAL_LENGTH];
1547*c43e99fdSEd Maste 	unsigned int i;
1548*c43e99fdSEd Maste 	struct evbuffer * buf = evbuffer_new();
1549*c43e99fdSEd Maste 
1550*c43e99fdSEd Maste 	tt_assert(buf);
1551*c43e99fdSEd Maste 
1552*c43e99fdSEd Maste 	/* make sure evbuffer_find doesn't match past the end of the buffer */
1553*c43e99fdSEd Maste 	evbuffer_add(buf, (unsigned char*)test1, strlen(test1));
1554*c43e99fdSEd Maste 	evbuffer_validate(buf);
1555*c43e99fdSEd Maste 	evbuffer_drain(buf, strlen(test1));
1556*c43e99fdSEd Maste 	evbuffer_validate(buf);
1557*c43e99fdSEd Maste 	evbuffer_add(buf, (unsigned char*)test2, strlen(test2));
1558*c43e99fdSEd Maste 	evbuffer_validate(buf);
1559*c43e99fdSEd Maste 	p = evbuffer_find(buf, (unsigned char*)"\r\n", 2);
1560*c43e99fdSEd Maste 	tt_want(p == NULL);
1561*c43e99fdSEd Maste 
1562*c43e99fdSEd Maste 	/*
1563*c43e99fdSEd Maste 	 * drain the buffer and do another find; in r309 this would
1564*c43e99fdSEd Maste 	 * read past the allocated buffer causing a valgrind error.
1565*c43e99fdSEd Maste 	 */
1566*c43e99fdSEd Maste 	evbuffer_drain(buf, strlen(test2));
1567*c43e99fdSEd Maste 	evbuffer_validate(buf);
1568*c43e99fdSEd Maste 	for (i = 0; i < EVBUFFER_INITIAL_LENGTH; ++i)
1569*c43e99fdSEd Maste 		test3[i] = 'a';
1570*c43e99fdSEd Maste 	test3[EVBUFFER_INITIAL_LENGTH - 1] = 'x';
1571*c43e99fdSEd Maste 	evbuffer_add(buf, (unsigned char *)test3, EVBUFFER_INITIAL_LENGTH);
1572*c43e99fdSEd Maste 	evbuffer_validate(buf);
1573*c43e99fdSEd Maste 	p = evbuffer_find(buf, (unsigned char *)"xy", 2);
1574*c43e99fdSEd Maste 	tt_want(p == NULL);
1575*c43e99fdSEd Maste 
1576*c43e99fdSEd Maste 	/* simple test for match at end of allocated buffer */
1577*c43e99fdSEd Maste 	p = evbuffer_find(buf, (unsigned char *)"ax", 2);
1578*c43e99fdSEd Maste 	tt_assert(p != NULL);
1579*c43e99fdSEd Maste 	tt_want(strncmp((char*)p, "ax", 2) == 0);
1580*c43e99fdSEd Maste 
1581*c43e99fdSEd Maste end:
1582*c43e99fdSEd Maste 	if (buf)
1583*c43e99fdSEd Maste 		evbuffer_free(buf);
1584*c43e99fdSEd Maste }
1585*c43e99fdSEd Maste 
1586*c43e99fdSEd Maste static void
1587*c43e99fdSEd Maste test_evbuffer_ptr_set(void *ptr)
1588*c43e99fdSEd Maste {
1589*c43e99fdSEd Maste 	struct evbuffer *buf = evbuffer_new();
1590*c43e99fdSEd Maste 	struct evbuffer_ptr pos;
1591*c43e99fdSEd Maste 	struct evbuffer_iovec v[1];
1592*c43e99fdSEd Maste 
1593*c43e99fdSEd Maste 	tt_assert(buf);
1594*c43e99fdSEd Maste 
1595*c43e99fdSEd Maste 	tt_int_op(evbuffer_get_length(buf), ==, 0);
1596*c43e99fdSEd Maste 
1597*c43e99fdSEd Maste 	tt_assert(evbuffer_ptr_set(buf, &pos, 0, EVBUFFER_PTR_SET) == 0);
1598*c43e99fdSEd Maste 	tt_assert(pos.pos == 0);
1599*c43e99fdSEd Maste 	tt_assert(evbuffer_ptr_set(buf, &pos, 1, EVBUFFER_PTR_ADD) == -1);
1600*c43e99fdSEd Maste 	tt_assert(pos.pos == -1);
1601*c43e99fdSEd Maste 	tt_assert(evbuffer_ptr_set(buf, &pos, 1, EVBUFFER_PTR_SET) == -1);
1602*c43e99fdSEd Maste 	tt_assert(pos.pos == -1);
1603*c43e99fdSEd Maste 
1604*c43e99fdSEd Maste 	/* create some chains */
1605*c43e99fdSEd Maste 	evbuffer_reserve_space(buf, 5000, v, 1);
1606*c43e99fdSEd Maste 	v[0].iov_len = 5000;
1607*c43e99fdSEd Maste 	memset(v[0].iov_base, 1, v[0].iov_len);
1608*c43e99fdSEd Maste 	evbuffer_commit_space(buf, v, 1);
1609*c43e99fdSEd Maste 	evbuffer_validate(buf);
1610*c43e99fdSEd Maste 
1611*c43e99fdSEd Maste 	evbuffer_reserve_space(buf, 4000, v, 1);
1612*c43e99fdSEd Maste 	v[0].iov_len = 4000;
1613*c43e99fdSEd Maste 	memset(v[0].iov_base, 2, v[0].iov_len);
1614*c43e99fdSEd Maste 	evbuffer_commit_space(buf, v, 1);
1615*c43e99fdSEd Maste 
1616*c43e99fdSEd Maste 	evbuffer_reserve_space(buf, 3000, v, 1);
1617*c43e99fdSEd Maste 	v[0].iov_len = 3000;
1618*c43e99fdSEd Maste 	memset(v[0].iov_base, 3, v[0].iov_len);
1619*c43e99fdSEd Maste 	evbuffer_commit_space(buf, v, 1);
1620*c43e99fdSEd Maste 	evbuffer_validate(buf);
1621*c43e99fdSEd Maste 
1622*c43e99fdSEd Maste 	tt_int_op(evbuffer_get_length(buf), ==, 12000);
1623*c43e99fdSEd Maste 
1624*c43e99fdSEd Maste 	tt_assert(evbuffer_ptr_set(buf, &pos, 13000, EVBUFFER_PTR_SET) == -1);
1625*c43e99fdSEd Maste 	tt_assert(pos.pos == -1);
1626*c43e99fdSEd Maste 	tt_assert(evbuffer_ptr_set(buf, &pos, 0, EVBUFFER_PTR_SET) == 0);
1627*c43e99fdSEd Maste 	tt_assert(pos.pos == 0);
1628*c43e99fdSEd Maste 	tt_assert(evbuffer_ptr_set(buf, &pos, 13000, EVBUFFER_PTR_ADD) == -1);
1629*c43e99fdSEd Maste 
1630*c43e99fdSEd Maste 	tt_assert(evbuffer_ptr_set(buf, &pos, 0, EVBUFFER_PTR_SET) == 0);
1631*c43e99fdSEd Maste 	tt_assert(pos.pos == 0);
1632*c43e99fdSEd Maste 	tt_assert(evbuffer_ptr_set(buf, &pos, 10000, EVBUFFER_PTR_ADD) == 0);
1633*c43e99fdSEd Maste 	tt_assert(pos.pos == 10000);
1634*c43e99fdSEd Maste 	tt_assert(evbuffer_ptr_set(buf, &pos, 1000, EVBUFFER_PTR_ADD) == 0);
1635*c43e99fdSEd Maste 	tt_assert(pos.pos == 11000);
1636*c43e99fdSEd Maste 	tt_assert(evbuffer_ptr_set(buf, &pos, 1000, EVBUFFER_PTR_ADD) == 0);
1637*c43e99fdSEd Maste 	tt_assert(pos.pos == 12000);
1638*c43e99fdSEd Maste 	tt_assert(evbuffer_ptr_set(buf, &pos, 1000, EVBUFFER_PTR_ADD) == -1);
1639*c43e99fdSEd Maste 	tt_assert(pos.pos == -1);
1640*c43e99fdSEd Maste 
1641*c43e99fdSEd Maste end:
1642*c43e99fdSEd Maste 	if (buf)
1643*c43e99fdSEd Maste 		evbuffer_free(buf);
1644*c43e99fdSEd Maste }
1645*c43e99fdSEd Maste 
1646*c43e99fdSEd Maste static void
1647*c43e99fdSEd Maste test_evbuffer_search(void *ptr)
1648*c43e99fdSEd Maste {
1649*c43e99fdSEd Maste 	struct evbuffer *buf = evbuffer_new();
1650*c43e99fdSEd Maste 	struct evbuffer *tmp = evbuffer_new();
1651*c43e99fdSEd Maste 	struct evbuffer_ptr pos, end;
1652*c43e99fdSEd Maste 
1653*c43e99fdSEd Maste 	tt_assert(buf);
1654*c43e99fdSEd Maste 	tt_assert(tmp);
1655*c43e99fdSEd Maste 
1656*c43e99fdSEd Maste 	pos = evbuffer_search(buf, "x", 1, NULL);
1657*c43e99fdSEd Maste 	tt_int_op(pos.pos, ==, -1);
1658*c43e99fdSEd Maste 	tt_assert(evbuffer_ptr_set(buf, &pos, 0, EVBUFFER_PTR_SET) == 0);
1659*c43e99fdSEd Maste 	pos = evbuffer_search(buf, "x", 1, &pos);
1660*c43e99fdSEd Maste 	tt_int_op(pos.pos, ==, -1);
1661*c43e99fdSEd Maste 	tt_assert(evbuffer_ptr_set(buf, &pos, 0, EVBUFFER_PTR_SET) == 0);
1662*c43e99fdSEd Maste 	pos = evbuffer_search_range(buf, "x", 1, &pos, &pos);
1663*c43e99fdSEd Maste 	tt_int_op(pos.pos, ==, -1);
1664*c43e99fdSEd Maste 	tt_assert(evbuffer_ptr_set(buf, &pos, 0, EVBUFFER_PTR_SET) == 0);
1665*c43e99fdSEd Maste 	pos = evbuffer_search_range(buf, "x", 1, &pos, NULL);
1666*c43e99fdSEd Maste 	tt_int_op(pos.pos, ==, -1);
1667*c43e99fdSEd Maste 
1668*c43e99fdSEd Maste 	/* set up our chains */
1669*c43e99fdSEd Maste 	evbuffer_add_printf(tmp, "hello");  /* 5 chars */
1670*c43e99fdSEd Maste 	evbuffer_add_buffer(buf, tmp);
1671*c43e99fdSEd Maste 	evbuffer_add_printf(tmp, "foo");    /* 3 chars */
1672*c43e99fdSEd Maste 	evbuffer_add_buffer(buf, tmp);
1673*c43e99fdSEd Maste 	evbuffer_add_printf(tmp, "cat");    /* 3 chars */
1674*c43e99fdSEd Maste 	evbuffer_add_buffer(buf, tmp);
1675*c43e99fdSEd Maste 	evbuffer_add_printf(tmp, "attack");
1676*c43e99fdSEd Maste 	evbuffer_add_buffer(buf, tmp);
1677*c43e99fdSEd Maste 
1678*c43e99fdSEd Maste 	pos = evbuffer_search(buf, "attack", 6, NULL);
1679*c43e99fdSEd Maste 	tt_int_op(pos.pos, ==, 11);
1680*c43e99fdSEd Maste 	pos = evbuffer_search(buf, "attacker", 8, NULL);
1681*c43e99fdSEd Maste 	tt_int_op(pos.pos, ==, -1);
1682*c43e99fdSEd Maste 
1683*c43e99fdSEd Maste 	/* test continuing search */
1684*c43e99fdSEd Maste 	pos = evbuffer_search(buf, "oc", 2, NULL);
1685*c43e99fdSEd Maste 	tt_int_op(pos.pos, ==, 7);
1686*c43e99fdSEd Maste 	pos = evbuffer_search(buf, "cat", 3, &pos);
1687*c43e99fdSEd Maste 	tt_int_op(pos.pos, ==, 8);
1688*c43e99fdSEd Maste 	pos = evbuffer_search(buf, "tacking", 7, &pos);
1689*c43e99fdSEd Maste 	tt_int_op(pos.pos, ==, -1);
1690*c43e99fdSEd Maste 
1691*c43e99fdSEd Maste 	evbuffer_ptr_set(buf, &pos, 5, EVBUFFER_PTR_SET);
1692*c43e99fdSEd Maste 	pos = evbuffer_search(buf, "foo", 3, &pos);
1693*c43e99fdSEd Maste 	tt_int_op(pos.pos, ==, 5);
1694*c43e99fdSEd Maste 
1695*c43e99fdSEd Maste 	evbuffer_ptr_set(buf, &pos, 2, EVBUFFER_PTR_ADD);
1696*c43e99fdSEd Maste 	pos = evbuffer_search(buf, "tat", 3, &pos);
1697*c43e99fdSEd Maste 	tt_int_op(pos.pos, ==, 10);
1698*c43e99fdSEd Maste 
1699*c43e99fdSEd Maste 	/* test bounded search. */
1700*c43e99fdSEd Maste 	/* Set "end" to the first t in "attack". */
1701*c43e99fdSEd Maste 	evbuffer_ptr_set(buf, &end, 12, EVBUFFER_PTR_SET);
1702*c43e99fdSEd Maste 	pos = evbuffer_search_range(buf, "foo", 3, NULL, &end);
1703*c43e99fdSEd Maste 	tt_int_op(pos.pos, ==, 5);
1704*c43e99fdSEd Maste 	pos = evbuffer_search_range(buf, "foocata", 7, NULL, &end);
1705*c43e99fdSEd Maste 	tt_int_op(pos.pos, ==, 5);
1706*c43e99fdSEd Maste 	pos = evbuffer_search_range(buf, "foocatat", 8, NULL, &end);
1707*c43e99fdSEd Maste 	tt_int_op(pos.pos, ==, -1);
1708*c43e99fdSEd Maste 	pos = evbuffer_search_range(buf, "ack", 3, NULL, &end);
1709*c43e99fdSEd Maste 	tt_int_op(pos.pos, ==, -1);
1710*c43e99fdSEd Maste 
1711*c43e99fdSEd Maste 	/* Set "end" after the last byte in the buffer. */
1712*c43e99fdSEd Maste 	tt_assert(evbuffer_ptr_set(buf, &end, 17, EVBUFFER_PTR_SET) == 0);
1713*c43e99fdSEd Maste 
1714*c43e99fdSEd Maste 	pos = evbuffer_search_range(buf, "attack", 6, NULL, &end);
1715*c43e99fdSEd Maste 	tt_int_op(pos.pos, ==, 11);
1716*c43e99fdSEd Maste 	tt_assert(evbuffer_ptr_set(buf, &pos, 11, EVBUFFER_PTR_SET) == 0);
1717*c43e99fdSEd Maste 	pos = evbuffer_search_range(buf, "attack", 6, &pos, &end);
1718*c43e99fdSEd Maste 	tt_int_op(pos.pos, ==, 11);
1719*c43e99fdSEd Maste 	tt_assert(evbuffer_ptr_set(buf, &pos, 17, EVBUFFER_PTR_SET) == 0);
1720*c43e99fdSEd Maste 	pos = evbuffer_search_range(buf, "attack", 6, &pos, &end);
1721*c43e99fdSEd Maste 	tt_int_op(pos.pos, ==, -1);
1722*c43e99fdSEd Maste 	tt_assert(evbuffer_ptr_set(buf, &pos, 17, EVBUFFER_PTR_SET) == 0);
1723*c43e99fdSEd Maste 	pos = evbuffer_search_range(buf, "attack", 6, &pos, NULL);
1724*c43e99fdSEd Maste 	tt_int_op(pos.pos, ==, -1);
1725*c43e99fdSEd Maste 
1726*c43e99fdSEd Maste end:
1727*c43e99fdSEd Maste 	if (buf)
1728*c43e99fdSEd Maste 		evbuffer_free(buf);
1729*c43e99fdSEd Maste 	if (tmp)
1730*c43e99fdSEd Maste 		evbuffer_free(tmp);
1731*c43e99fdSEd Maste }
1732*c43e99fdSEd Maste 
1733*c43e99fdSEd Maste static void
1734*c43e99fdSEd Maste log_change_callback(struct evbuffer *buffer,
1735*c43e99fdSEd Maste     const struct evbuffer_cb_info *cbinfo,
1736*c43e99fdSEd Maste     void *arg)
1737*c43e99fdSEd Maste {
1738*c43e99fdSEd Maste 
1739*c43e99fdSEd Maste 	size_t old_len = cbinfo->orig_size;
1740*c43e99fdSEd Maste 	size_t new_len = old_len + cbinfo->n_added - cbinfo->n_deleted;
1741*c43e99fdSEd Maste 	struct evbuffer *out = arg;
1742*c43e99fdSEd Maste 	evbuffer_add_printf(out, "%lu->%lu; ", (unsigned long)old_len,
1743*c43e99fdSEd Maste 			    (unsigned long)new_len);
1744*c43e99fdSEd Maste }
1745*c43e99fdSEd Maste static void
1746*c43e99fdSEd Maste self_draining_callback(struct evbuffer *evbuffer, size_t old_len,
1747*c43e99fdSEd Maste 		size_t new_len, void *arg)
1748*c43e99fdSEd Maste {
1749*c43e99fdSEd Maste 	if (new_len > old_len)
1750*c43e99fdSEd Maste 		evbuffer_drain(evbuffer, new_len);
1751*c43e99fdSEd Maste }
1752*c43e99fdSEd Maste 
1753*c43e99fdSEd Maste static void
1754*c43e99fdSEd Maste test_evbuffer_callbacks(void *ptr)
1755*c43e99fdSEd Maste {
1756*c43e99fdSEd Maste 	struct evbuffer *buf = evbuffer_new();
1757*c43e99fdSEd Maste 	struct evbuffer *buf_out1 = evbuffer_new();
1758*c43e99fdSEd Maste 	struct evbuffer *buf_out2 = evbuffer_new();
1759*c43e99fdSEd Maste 	struct evbuffer_cb_entry *cb1, *cb2;
1760*c43e99fdSEd Maste 
1761*c43e99fdSEd Maste 	tt_assert(buf);
1762*c43e99fdSEd Maste 	tt_assert(buf_out1);
1763*c43e99fdSEd Maste 	tt_assert(buf_out2);
1764*c43e99fdSEd Maste 
1765*c43e99fdSEd Maste 	cb1 = evbuffer_add_cb(buf, log_change_callback, buf_out1);
1766*c43e99fdSEd Maste 	cb2 = evbuffer_add_cb(buf, log_change_callback, buf_out2);
1767*c43e99fdSEd Maste 
1768*c43e99fdSEd Maste 	/* Let's run through adding and deleting some stuff from the buffer
1769*c43e99fdSEd Maste 	 * and turning the callbacks on and off and removing them.  The callback
1770*c43e99fdSEd Maste 	 * adds a summary of length changes to buf_out1/buf_out2 when called. */
1771*c43e99fdSEd Maste 	/* size: 0-> 36. */
1772*c43e99fdSEd Maste 	evbuffer_add_printf(buf, "The %d magic words are spotty pudding", 2);
1773*c43e99fdSEd Maste 	evbuffer_validate(buf);
1774*c43e99fdSEd Maste 	evbuffer_cb_clear_flags(buf, cb2, EVBUFFER_CB_ENABLED);
1775*c43e99fdSEd Maste 	evbuffer_drain(buf, 10); /*36->26*/
1776*c43e99fdSEd Maste 	evbuffer_validate(buf);
1777*c43e99fdSEd Maste 	evbuffer_prepend(buf, "Hello", 5);/*26->31*/
1778*c43e99fdSEd Maste 	evbuffer_cb_set_flags(buf, cb2, EVBUFFER_CB_ENABLED);
1779*c43e99fdSEd Maste 	evbuffer_add_reference(buf, "Goodbye", 7, NULL, NULL); /*31->38*/
1780*c43e99fdSEd Maste 	evbuffer_remove_cb_entry(buf, cb1);
1781*c43e99fdSEd Maste 	evbuffer_validate(buf);
1782*c43e99fdSEd Maste 	evbuffer_drain(buf, evbuffer_get_length(buf)); /*38->0*/;
1783*c43e99fdSEd Maste 	tt_assert(-1 == evbuffer_remove_cb(buf, log_change_callback, NULL));
1784*c43e99fdSEd Maste 	evbuffer_add(buf, "X", 1); /* 0->1 */
1785*c43e99fdSEd Maste 	tt_assert(!evbuffer_remove_cb(buf, log_change_callback, buf_out2));
1786*c43e99fdSEd Maste 	evbuffer_validate(buf);
1787*c43e99fdSEd Maste 
1788*c43e99fdSEd Maste 	tt_str_op((const char *) evbuffer_pullup(buf_out1, -1), ==,
1789*c43e99fdSEd Maste 		  "0->36; 36->26; 26->31; 31->38; ");
1790*c43e99fdSEd Maste 	tt_str_op((const char *) evbuffer_pullup(buf_out2, -1), ==,
1791*c43e99fdSEd Maste 		  "0->36; 31->38; 38->0; 0->1; ");
1792*c43e99fdSEd Maste 	evbuffer_drain(buf_out1, evbuffer_get_length(buf_out1));
1793*c43e99fdSEd Maste 	evbuffer_drain(buf_out2, evbuffer_get_length(buf_out2));
1794*c43e99fdSEd Maste 	/* Let's test the obsolete buffer_setcb function too. */
1795*c43e99fdSEd Maste 	cb1 = evbuffer_add_cb(buf, log_change_callback, buf_out1);
1796*c43e99fdSEd Maste 	tt_assert(cb1 != NULL);
1797*c43e99fdSEd Maste 	cb2 = evbuffer_add_cb(buf, log_change_callback, buf_out2);
1798*c43e99fdSEd Maste 	tt_assert(cb2 != NULL);
1799*c43e99fdSEd Maste 	evbuffer_setcb(buf, self_draining_callback, NULL);
1800*c43e99fdSEd Maste 	evbuffer_add_printf(buf, "This should get drained right away.");
1801*c43e99fdSEd Maste 	tt_uint_op(evbuffer_get_length(buf), ==, 0);
1802*c43e99fdSEd Maste 	tt_uint_op(evbuffer_get_length(buf_out1), ==, 0);
1803*c43e99fdSEd Maste 	tt_uint_op(evbuffer_get_length(buf_out2), ==, 0);
1804*c43e99fdSEd Maste 	evbuffer_setcb(buf, NULL, NULL);
1805*c43e99fdSEd Maste 	evbuffer_add_printf(buf, "This will not.");
1806*c43e99fdSEd Maste 	tt_str_op((const char *) evbuffer_pullup(buf, -1), ==, "This will not.");
1807*c43e99fdSEd Maste 	evbuffer_validate(buf);
1808*c43e99fdSEd Maste 	evbuffer_drain(buf, evbuffer_get_length(buf));
1809*c43e99fdSEd Maste 	evbuffer_validate(buf);
1810*c43e99fdSEd Maste #if 0
1811*c43e99fdSEd Maste 	/* Now let's try a suspended callback. */
1812*c43e99fdSEd Maste 	cb1 = evbuffer_add_cb(buf, log_change_callback, buf_out1);
1813*c43e99fdSEd Maste 	cb2 = evbuffer_add_cb(buf, log_change_callback, buf_out2);
1814*c43e99fdSEd Maste 	evbuffer_cb_suspend(buf,cb2);
1815*c43e99fdSEd Maste 	evbuffer_prepend(buf,"Hello world",11); /*0->11*/
1816*c43e99fdSEd Maste 	evbuffer_validate(buf);
1817*c43e99fdSEd Maste 	evbuffer_cb_suspend(buf,cb1);
1818*c43e99fdSEd Maste 	evbuffer_add(buf,"more",4); /* 11->15 */
1819*c43e99fdSEd Maste 	evbuffer_cb_unsuspend(buf,cb2);
1820*c43e99fdSEd Maste 	evbuffer_drain(buf, 4); /* 15->11 */
1821*c43e99fdSEd Maste 	evbuffer_cb_unsuspend(buf,cb1);
1822*c43e99fdSEd Maste 	evbuffer_drain(buf, evbuffer_get_length(buf)); /* 11->0 */
1823*c43e99fdSEd Maste 
1824*c43e99fdSEd Maste 	tt_str_op(evbuffer_pullup(buf_out1, -1), ==,
1825*c43e99fdSEd Maste 		  "0->11; 11->11; 11->0; ");
1826*c43e99fdSEd Maste 	tt_str_op(evbuffer_pullup(buf_out2, -1), ==,
1827*c43e99fdSEd Maste 		  "0->15; 15->11; 11->0; ");
1828*c43e99fdSEd Maste #endif
1829*c43e99fdSEd Maste 
1830*c43e99fdSEd Maste  end:
1831*c43e99fdSEd Maste 	if (buf)
1832*c43e99fdSEd Maste 		evbuffer_free(buf);
1833*c43e99fdSEd Maste 	if (buf_out1)
1834*c43e99fdSEd Maste 		evbuffer_free(buf_out1);
1835*c43e99fdSEd Maste 	if (buf_out2)
1836*c43e99fdSEd Maste 		evbuffer_free(buf_out2);
1837*c43e99fdSEd Maste }
1838*c43e99fdSEd Maste 
1839*c43e99fdSEd Maste static int ref_done_cb_called_count = 0;
1840*c43e99fdSEd Maste static void *ref_done_cb_called_with = NULL;
1841*c43e99fdSEd Maste static const void *ref_done_cb_called_with_data = NULL;
1842*c43e99fdSEd Maste static size_t ref_done_cb_called_with_len = 0;
1843*c43e99fdSEd Maste static void ref_done_cb(const void *data, size_t len, void *info)
1844*c43e99fdSEd Maste {
1845*c43e99fdSEd Maste 	++ref_done_cb_called_count;
1846*c43e99fdSEd Maste 	ref_done_cb_called_with = info;
1847*c43e99fdSEd Maste 	ref_done_cb_called_with_data = data;
1848*c43e99fdSEd Maste 	ref_done_cb_called_with_len = len;
1849*c43e99fdSEd Maste }
1850*c43e99fdSEd Maste 
1851*c43e99fdSEd Maste static void
1852*c43e99fdSEd Maste test_evbuffer_add_reference(void *ptr)
1853*c43e99fdSEd Maste {
1854*c43e99fdSEd Maste 	const char chunk1[] = "If you have found the answer to such a problem";
1855*c43e99fdSEd Maste 	const char chunk2[] = "you ought to write it up for publication";
1856*c43e99fdSEd Maste 			  /* -- Knuth's "Notes on the Exercises" from TAOCP */
1857*c43e99fdSEd Maste 	char tmp[16];
1858*c43e99fdSEd Maste 	size_t len1 = strlen(chunk1), len2=strlen(chunk2);
1859*c43e99fdSEd Maste 
1860*c43e99fdSEd Maste 	struct evbuffer *buf1 = NULL, *buf2 = NULL;
1861*c43e99fdSEd Maste 
1862*c43e99fdSEd Maste 	buf1 = evbuffer_new();
1863*c43e99fdSEd Maste 	tt_assert(buf1);
1864*c43e99fdSEd Maste 
1865*c43e99fdSEd Maste 	evbuffer_add_reference(buf1, chunk1, len1, ref_done_cb, (void*)111);
1866*c43e99fdSEd Maste 	evbuffer_add(buf1, ", ", 2);
1867*c43e99fdSEd Maste 	evbuffer_add_reference(buf1, chunk2, len2, ref_done_cb, (void*)222);
1868*c43e99fdSEd Maste 	tt_int_op(evbuffer_get_length(buf1), ==, len1+len2+2);
1869*c43e99fdSEd Maste 
1870*c43e99fdSEd Maste 	/* Make sure we can drain a little from a reference. */
1871*c43e99fdSEd Maste 	tt_int_op(evbuffer_remove(buf1, tmp, 6), ==, 6);
1872*c43e99fdSEd Maste 	tt_int_op(memcmp(tmp, "If you", 6), ==, 0);
1873*c43e99fdSEd Maste 	tt_int_op(evbuffer_remove(buf1, tmp, 5), ==, 5);
1874*c43e99fdSEd Maste 	tt_int_op(memcmp(tmp, " have", 5), ==, 0);
1875*c43e99fdSEd Maste 
1876*c43e99fdSEd Maste 	/* Make sure that prepending does not meddle with immutable data */
1877*c43e99fdSEd Maste 	tt_int_op(evbuffer_prepend(buf1, "I have ", 7), ==, 0);
1878*c43e99fdSEd Maste 	tt_int_op(memcmp(chunk1, "If you", 6), ==, 0);
1879*c43e99fdSEd Maste 	evbuffer_validate(buf1);
1880*c43e99fdSEd Maste 
1881*c43e99fdSEd Maste 	/* Make sure that when the chunk is over, the callback is invoked. */
1882*c43e99fdSEd Maste 	evbuffer_drain(buf1, 7); /* Remove prepended stuff. */
1883*c43e99fdSEd Maste 	evbuffer_drain(buf1, len1-11-1); /* remove all but one byte of chunk1 */
1884*c43e99fdSEd Maste 	tt_int_op(ref_done_cb_called_count, ==, 0);
1885*c43e99fdSEd Maste 	evbuffer_remove(buf1, tmp, 1);
1886*c43e99fdSEd Maste 	tt_int_op(tmp[0], ==, 'm');
1887*c43e99fdSEd Maste 	tt_assert(ref_done_cb_called_with == (void*)111);
1888*c43e99fdSEd Maste 	tt_assert(ref_done_cb_called_with_data == chunk1);
1889*c43e99fdSEd Maste 	tt_assert(ref_done_cb_called_with_len == len1);
1890*c43e99fdSEd Maste 	tt_int_op(ref_done_cb_called_count, ==, 1);
1891*c43e99fdSEd Maste 	evbuffer_validate(buf1);
1892*c43e99fdSEd Maste 
1893*c43e99fdSEd Maste 	/* Drain some of the remaining chunk, then add it to another buffer */
1894*c43e99fdSEd Maste 	evbuffer_drain(buf1, 6); /* Remove the ", you ". */
1895*c43e99fdSEd Maste 	buf2 = evbuffer_new();
1896*c43e99fdSEd Maste 	tt_assert(buf2);
1897*c43e99fdSEd Maste 	tt_int_op(ref_done_cb_called_count, ==, 1);
1898*c43e99fdSEd Maste 	evbuffer_add(buf2, "I ", 2);
1899*c43e99fdSEd Maste 
1900*c43e99fdSEd Maste 	evbuffer_add_buffer(buf2, buf1);
1901*c43e99fdSEd Maste 	tt_int_op(ref_done_cb_called_count, ==, 1);
1902*c43e99fdSEd Maste 	evbuffer_remove(buf2, tmp, 16);
1903*c43e99fdSEd Maste 	tt_int_op(memcmp("I ought to write", tmp, 16), ==, 0);
1904*c43e99fdSEd Maste 	evbuffer_drain(buf2, evbuffer_get_length(buf2));
1905*c43e99fdSEd Maste 	tt_int_op(ref_done_cb_called_count, ==, 2);
1906*c43e99fdSEd Maste 	tt_assert(ref_done_cb_called_with == (void*)222);
1907*c43e99fdSEd Maste 	evbuffer_validate(buf2);
1908*c43e99fdSEd Maste 
1909*c43e99fdSEd Maste 	/* Now add more stuff to buf1 and make sure that it gets removed on
1910*c43e99fdSEd Maste 	 * free. */
1911*c43e99fdSEd Maste 	evbuffer_add(buf1, "You shake and shake the ", 24);
1912*c43e99fdSEd Maste 	evbuffer_add_reference(buf1, "ketchup bottle", 14, ref_done_cb,
1913*c43e99fdSEd Maste 	    (void*)3333);
1914*c43e99fdSEd Maste 	evbuffer_add(buf1, ". Nothing comes and then a lot'll.", 35);
1915*c43e99fdSEd Maste 	evbuffer_free(buf1);
1916*c43e99fdSEd Maste 	buf1 = NULL;
1917*c43e99fdSEd Maste 	tt_int_op(ref_done_cb_called_count, ==, 3);
1918*c43e99fdSEd Maste 	tt_assert(ref_done_cb_called_with == (void*)3333);
1919*c43e99fdSEd Maste 
1920*c43e99fdSEd Maste end:
1921*c43e99fdSEd Maste 	if (buf1)
1922*c43e99fdSEd Maste 		evbuffer_free(buf1);
1923*c43e99fdSEd Maste 	if (buf2)
1924*c43e99fdSEd Maste 		evbuffer_free(buf2);
1925*c43e99fdSEd Maste }
1926*c43e99fdSEd Maste 
1927*c43e99fdSEd Maste static void
1928*c43e99fdSEd Maste test_evbuffer_multicast(void *ptr)
1929*c43e99fdSEd Maste {
1930*c43e99fdSEd Maste 	const char chunk1[] = "If you have found the answer to such a problem";
1931*c43e99fdSEd Maste 	const char chunk2[] = "you ought to write it up for publication";
1932*c43e99fdSEd Maste 			  /* -- Knuth's "Notes on the Exercises" from TAOCP */
1933*c43e99fdSEd Maste 	char tmp[16];
1934*c43e99fdSEd Maste 	size_t len1 = strlen(chunk1), len2=strlen(chunk2);
1935*c43e99fdSEd Maste 
1936*c43e99fdSEd Maste 	struct evbuffer *buf1 = NULL, *buf2 = NULL;
1937*c43e99fdSEd Maste 
1938*c43e99fdSEd Maste 	buf1 = evbuffer_new();
1939*c43e99fdSEd Maste 	tt_assert(buf1);
1940*c43e99fdSEd Maste 
1941*c43e99fdSEd Maste 	evbuffer_add(buf1, chunk1, len1);
1942*c43e99fdSEd Maste 	evbuffer_add(buf1, ", ", 2);
1943*c43e99fdSEd Maste 	evbuffer_add(buf1, chunk2, len2);
1944*c43e99fdSEd Maste 	tt_int_op(evbuffer_get_length(buf1), ==, len1+len2+2);
1945*c43e99fdSEd Maste 
1946*c43e99fdSEd Maste 	buf2 = evbuffer_new();
1947*c43e99fdSEd Maste 	tt_assert(buf2);
1948*c43e99fdSEd Maste 
1949*c43e99fdSEd Maste 	tt_int_op(evbuffer_add_buffer_reference(buf2, buf1), ==, 0);
1950*c43e99fdSEd Maste 	/* nested references are not allowed */
1951*c43e99fdSEd Maste 	tt_int_op(evbuffer_add_buffer_reference(buf2, buf2), ==, -1);
1952*c43e99fdSEd Maste 	tt_int_op(evbuffer_add_buffer_reference(buf1, buf2), ==, -1);
1953*c43e99fdSEd Maste 
1954*c43e99fdSEd Maste 	/* both buffers contain the same amount of data */
1955*c43e99fdSEd Maste 	tt_int_op(evbuffer_get_length(buf1), ==, evbuffer_get_length(buf1));
1956*c43e99fdSEd Maste 
1957*c43e99fdSEd Maste 	/* Make sure we can drain a little from the first buffer. */
1958*c43e99fdSEd Maste 	tt_int_op(evbuffer_remove(buf1, tmp, 6), ==, 6);
1959*c43e99fdSEd Maste 	tt_int_op(memcmp(tmp, "If you", 6), ==, 0);
1960*c43e99fdSEd Maste 	tt_int_op(evbuffer_remove(buf1, tmp, 5), ==, 5);
1961*c43e99fdSEd Maste 	tt_int_op(memcmp(tmp, " have", 5), ==, 0);
1962*c43e99fdSEd Maste 
1963*c43e99fdSEd Maste 	/* Make sure that prepending does not meddle with immutable data */
1964*c43e99fdSEd Maste 	tt_int_op(evbuffer_prepend(buf1, "I have ", 7), ==, 0);
1965*c43e99fdSEd Maste 	tt_int_op(memcmp(chunk1, "If you", 6), ==, 0);
1966*c43e99fdSEd Maste 	evbuffer_validate(buf1);
1967*c43e99fdSEd Maste 
1968*c43e99fdSEd Maste 	/* Make sure we can drain a little from the second buffer. */
1969*c43e99fdSEd Maste 	tt_int_op(evbuffer_remove(buf2, tmp, 6), ==, 6);
1970*c43e99fdSEd Maste 	tt_int_op(memcmp(tmp, "If you", 6), ==, 0);
1971*c43e99fdSEd Maste 	tt_int_op(evbuffer_remove(buf2, tmp, 5), ==, 5);
1972*c43e99fdSEd Maste 	tt_int_op(memcmp(tmp, " have", 5), ==, 0);
1973*c43e99fdSEd Maste 
1974*c43e99fdSEd Maste 	/* Make sure that prepending does not meddle with immutable data */
1975*c43e99fdSEd Maste 	tt_int_op(evbuffer_prepend(buf2, "I have ", 7), ==, 0);
1976*c43e99fdSEd Maste 	tt_int_op(memcmp(chunk1, "If you", 6), ==, 0);
1977*c43e99fdSEd Maste 	evbuffer_validate(buf2);
1978*c43e99fdSEd Maste 
1979*c43e99fdSEd Maste 	/* Make sure the data can be read from the second buffer when the first is freed */
1980*c43e99fdSEd Maste 	evbuffer_free(buf1);
1981*c43e99fdSEd Maste 	buf1 = NULL;
1982*c43e99fdSEd Maste 
1983*c43e99fdSEd Maste 	tt_int_op(evbuffer_remove(buf2, tmp, 6), ==, 6);
1984*c43e99fdSEd Maste 	tt_int_op(memcmp(tmp, "I have", 6), ==, 0);
1985*c43e99fdSEd Maste 
1986*c43e99fdSEd Maste 	tt_int_op(evbuffer_remove(buf2, tmp, 6), ==, 6);
1987*c43e99fdSEd Maste 	tt_int_op(memcmp(tmp, "  foun", 6), ==, 0);
1988*c43e99fdSEd Maste 
1989*c43e99fdSEd Maste end:
1990*c43e99fdSEd Maste 	if (buf1)
1991*c43e99fdSEd Maste 		evbuffer_free(buf1);
1992*c43e99fdSEd Maste 	if (buf2)
1993*c43e99fdSEd Maste 		evbuffer_free(buf2);
1994*c43e99fdSEd Maste }
1995*c43e99fdSEd Maste 
1996*c43e99fdSEd Maste static void
1997*c43e99fdSEd Maste test_evbuffer_multicast_drain(void *ptr)
1998*c43e99fdSEd Maste {
1999*c43e99fdSEd Maste 	const char chunk1[] = "If you have found the answer to such a problem";
2000*c43e99fdSEd Maste 	const char chunk2[] = "you ought to write it up for publication";
2001*c43e99fdSEd Maste 			  /* -- Knuth's "Notes on the Exercises" from TAOCP */
2002*c43e99fdSEd Maste 	size_t len1 = strlen(chunk1), len2=strlen(chunk2);
2003*c43e99fdSEd Maste 
2004*c43e99fdSEd Maste 	struct evbuffer *buf1 = NULL, *buf2 = NULL;
2005*c43e99fdSEd Maste 
2006*c43e99fdSEd Maste 	buf1 = evbuffer_new();
2007*c43e99fdSEd Maste 	tt_assert(buf1);
2008*c43e99fdSEd Maste 
2009*c43e99fdSEd Maste 	evbuffer_add(buf1, chunk1, len1);
2010*c43e99fdSEd Maste 	evbuffer_add(buf1, ", ", 2);
2011*c43e99fdSEd Maste 	evbuffer_add(buf1, chunk2, len2);
2012*c43e99fdSEd Maste 	tt_int_op(evbuffer_get_length(buf1), ==, len1+len2+2);
2013*c43e99fdSEd Maste 
2014*c43e99fdSEd Maste 	buf2 = evbuffer_new();
2015*c43e99fdSEd Maste 	tt_assert(buf2);
2016*c43e99fdSEd Maste 
2017*c43e99fdSEd Maste 	tt_int_op(evbuffer_add_buffer_reference(buf2, buf1), ==, 0);
2018*c43e99fdSEd Maste 	tt_int_op(evbuffer_get_length(buf2), ==, len1+len2+2);
2019*c43e99fdSEd Maste 	tt_int_op(evbuffer_drain(buf1, evbuffer_get_length(buf1)), ==, 0);
2020*c43e99fdSEd Maste 	tt_int_op(evbuffer_get_length(buf2), ==, len1+len2+2);
2021*c43e99fdSEd Maste 	tt_int_op(evbuffer_drain(buf2, evbuffer_get_length(buf2)), ==, 0);
2022*c43e99fdSEd Maste 	evbuffer_validate(buf1);
2023*c43e99fdSEd Maste 	evbuffer_validate(buf2);
2024*c43e99fdSEd Maste 
2025*c43e99fdSEd Maste end:
2026*c43e99fdSEd Maste 	if (buf1)
2027*c43e99fdSEd Maste 		evbuffer_free(buf1);
2028*c43e99fdSEd Maste 	if (buf2)
2029*c43e99fdSEd Maste 		evbuffer_free(buf2);
2030*c43e99fdSEd Maste }
2031*c43e99fdSEd Maste 
2032*c43e99fdSEd Maste static void
2033*c43e99fdSEd Maste check_prepend(struct evbuffer *buffer,
2034*c43e99fdSEd Maste     const struct evbuffer_cb_info *cbinfo,
2035*c43e99fdSEd Maste     void *arg)
2036*c43e99fdSEd Maste {
2037*c43e99fdSEd Maste 	tt_int_op(cbinfo->orig_size, ==, 3);
2038*c43e99fdSEd Maste 	tt_int_op(cbinfo->n_added, ==, 8096);
2039*c43e99fdSEd Maste 	tt_int_op(cbinfo->n_deleted, ==, 0);
2040*c43e99fdSEd Maste end:
2041*c43e99fdSEd Maste 	;
2042*c43e99fdSEd Maste }
2043*c43e99fdSEd Maste /* Some cases that we didn't get in test_evbuffer() above, for more coverage. */
2044*c43e99fdSEd Maste static void
2045*c43e99fdSEd Maste test_evbuffer_prepend(void *ptr)
2046*c43e99fdSEd Maste {
2047*c43e99fdSEd Maste 	struct evbuffer *buf1 = NULL, *buf2 = NULL;
2048*c43e99fdSEd Maste 	char tmp[128], *buffer = malloc(8096);
2049*c43e99fdSEd Maste 	int n;
2050*c43e99fdSEd Maste 
2051*c43e99fdSEd Maste 	buf1 = evbuffer_new();
2052*c43e99fdSEd Maste 	tt_assert(buf1);
2053*c43e99fdSEd Maste 
2054*c43e99fdSEd Maste 	/* Case 0: The evbuffer is entirely empty. */
2055*c43e99fdSEd Maste 	evbuffer_prepend(buf1, "This string has 29 characters", 29);
2056*c43e99fdSEd Maste 	evbuffer_validate(buf1);
2057*c43e99fdSEd Maste 
2058*c43e99fdSEd Maste 	/* Case 1: Prepend goes entirely in new chunk. */
2059*c43e99fdSEd Maste 	evbuffer_prepend(buf1, "Short.", 6);
2060*c43e99fdSEd Maste 	evbuffer_validate(buf1);
2061*c43e99fdSEd Maste 
2062*c43e99fdSEd Maste 	/* Case 2: prepend goes entirely in first chunk. */
2063*c43e99fdSEd Maste 	evbuffer_drain(buf1, 6+11);
2064*c43e99fdSEd Maste 	evbuffer_prepend(buf1, "it", 2);
2065*c43e99fdSEd Maste 	evbuffer_validate(buf1);
2066*c43e99fdSEd Maste 	tt_assert(!memcmp(buf1->first->buffer+buf1->first->misalign,
2067*c43e99fdSEd Maste 		"it has", 6));
2068*c43e99fdSEd Maste 
2069*c43e99fdSEd Maste 	/* Case 3: prepend is split over multiple chunks. */
2070*c43e99fdSEd Maste 	evbuffer_prepend(buf1, "It is no longer true to say ", 28);
2071*c43e99fdSEd Maste 	evbuffer_validate(buf1);
2072*c43e99fdSEd Maste 	n = evbuffer_remove(buf1, tmp, sizeof(tmp)-1);
2073*c43e99fdSEd Maste 	tt_int_op(n, >=, 0);
2074*c43e99fdSEd Maste 	tmp[n]='\0';
2075*c43e99fdSEd Maste 	tt_str_op(tmp,==,"It is no longer true to say it has 29 characters");
2076*c43e99fdSEd Maste 
2077*c43e99fdSEd Maste 	buf2 = evbuffer_new();
2078*c43e99fdSEd Maste 	tt_assert(buf2);
2079*c43e99fdSEd Maste 
2080*c43e99fdSEd Maste 	/* Case 4: prepend a buffer to an empty buffer. */
2081*c43e99fdSEd Maste 	n = 999;
2082*c43e99fdSEd Maste 	evbuffer_add_printf(buf1, "Here is string %d. ", n++);
2083*c43e99fdSEd Maste 	evbuffer_prepend_buffer(buf2, buf1);
2084*c43e99fdSEd Maste 	evbuffer_validate(buf2);
2085*c43e99fdSEd Maste 
2086*c43e99fdSEd Maste 	/* Case 5: prepend a buffer to a nonempty buffer. */
2087*c43e99fdSEd Maste 	evbuffer_add_printf(buf1, "Here is string %d. ", n++);
2088*c43e99fdSEd Maste 	evbuffer_prepend_buffer(buf2, buf1);
2089*c43e99fdSEd Maste 	evbuffer_validate(buf2);
2090*c43e99fdSEd Maste 	evbuffer_validate(buf1);
2091*c43e99fdSEd Maste 	n = evbuffer_remove(buf2, tmp, sizeof(tmp)-1);
2092*c43e99fdSEd Maste 	tt_int_op(n, >=, 0);
2093*c43e99fdSEd Maste 	tmp[n]='\0';
2094*c43e99fdSEd Maste 	tt_str_op(tmp,==,"Here is string 1000. Here is string 999. ");
2095*c43e99fdSEd Maste 
2096*c43e99fdSEd Maste 	/* Case 5: evbuffer_prepend() will need a new buffer, with callbacks */
2097*c43e99fdSEd Maste 	memset(buffer, 'A', 8096);
2098*c43e99fdSEd Maste 	evbuffer_free(buf2);
2099*c43e99fdSEd Maste 	buf2 = evbuffer_new();
2100*c43e99fdSEd Maste 	tt_assert(buf2);
2101*c43e99fdSEd Maste 	evbuffer_prepend(buf2, "foo", 3);
2102*c43e99fdSEd Maste 	evbuffer_add_cb(buf2, check_prepend, NULL);
2103*c43e99fdSEd Maste 	evbuffer_prepend(buf2, buffer, 8096);
2104*c43e99fdSEd Maste 	evbuffer_remove_cb(buf2, check_prepend, NULL);
2105*c43e99fdSEd Maste 	evbuffer_validate(buf2);
2106*c43e99fdSEd Maste 	tt_nstr_op(8096,(char *)evbuffer_pullup(buf2, 8096),==,buffer);
2107*c43e99fdSEd Maste 	evbuffer_drain(buf2, 8096);
2108*c43e99fdSEd Maste 	tt_nstr_op(3,(char *)evbuffer_pullup(buf2, 3),==,"foo");
2109*c43e99fdSEd Maste 	evbuffer_drain(buf2, 3);
2110*c43e99fdSEd Maste 
2111*c43e99fdSEd Maste end:
2112*c43e99fdSEd Maste 	free(buffer);
2113*c43e99fdSEd Maste 	if (buf1)
2114*c43e99fdSEd Maste 		evbuffer_free(buf1);
2115*c43e99fdSEd Maste 	if (buf2)
2116*c43e99fdSEd Maste 		evbuffer_free(buf2);
2117*c43e99fdSEd Maste 
2118*c43e99fdSEd Maste }
2119*c43e99fdSEd Maste 
2120*c43e99fdSEd Maste static void
2121*c43e99fdSEd Maste test_evbuffer_peek_first_gt(void *info)
2122*c43e99fdSEd Maste {
2123*c43e99fdSEd Maste 	struct evbuffer *buf = NULL, *tmp_buf = NULL;
2124*c43e99fdSEd Maste 	struct evbuffer_ptr ptr;
2125*c43e99fdSEd Maste 	struct evbuffer_iovec v[2];
2126*c43e99fdSEd Maste 
2127*c43e99fdSEd Maste 	buf = evbuffer_new();
2128*c43e99fdSEd Maste 	tmp_buf = evbuffer_new();
2129*c43e99fdSEd Maste 	evbuffer_add_printf(tmp_buf, "Contents of chunk 100\n");
2130*c43e99fdSEd Maste 	evbuffer_add_buffer(buf, tmp_buf);
2131*c43e99fdSEd Maste 	evbuffer_add_printf(tmp_buf, "Contents of chunk 1\n");
2132*c43e99fdSEd Maste 	evbuffer_add_buffer(buf, tmp_buf);
2133*c43e99fdSEd Maste 
2134*c43e99fdSEd Maste 	evbuffer_ptr_set(buf, &ptr, 0, EVBUFFER_PTR_SET);
2135*c43e99fdSEd Maste 
2136*c43e99fdSEd Maste 	/** The only case that matters*/
2137*c43e99fdSEd Maste 	tt_int_op(evbuffer_peek(buf, -1, &ptr, NULL, 0), ==, 2);
2138*c43e99fdSEd Maste 	/** Just in case */
2139*c43e99fdSEd Maste 	tt_int_op(evbuffer_peek(buf, -1, &ptr, v, 2), ==, 2);
2140*c43e99fdSEd Maste 
2141*c43e99fdSEd Maste 	evbuffer_ptr_set(buf, &ptr, 20, EVBUFFER_PTR_ADD);
2142*c43e99fdSEd Maste 	tt_int_op(evbuffer_peek(buf, -1, &ptr, NULL, 0), ==, 2);
2143*c43e99fdSEd Maste 	tt_int_op(evbuffer_peek(buf, -1, &ptr, v, 2), ==, 2);
2144*c43e99fdSEd Maste 	tt_int_op(evbuffer_peek(buf, 2, &ptr, NULL, 0), ==, 1);
2145*c43e99fdSEd Maste 	tt_int_op(evbuffer_peek(buf, 2, &ptr, v, 2), ==, 1);
2146*c43e99fdSEd Maste 	tt_int_op(evbuffer_peek(buf, 3, &ptr, NULL, 0), ==, 2);
2147*c43e99fdSEd Maste 	tt_int_op(evbuffer_peek(buf, 3, &ptr, v, 2), ==, 2);
2148*c43e99fdSEd Maste 
2149*c43e99fdSEd Maste end:
2150*c43e99fdSEd Maste 	if (buf)
2151*c43e99fdSEd Maste 		evbuffer_free(buf);
2152*c43e99fdSEd Maste 	if (tmp_buf)
2153*c43e99fdSEd Maste 		evbuffer_free(tmp_buf);
2154*c43e99fdSEd Maste }
2155*c43e99fdSEd Maste 
2156*c43e99fdSEd Maste static void
2157*c43e99fdSEd Maste test_evbuffer_peek(void *info)
2158*c43e99fdSEd Maste {
2159*c43e99fdSEd Maste 	struct evbuffer *buf = NULL, *tmp_buf = NULL;
2160*c43e99fdSEd Maste 	int i;
2161*c43e99fdSEd Maste 	struct evbuffer_iovec v[20];
2162*c43e99fdSEd Maste 	struct evbuffer_ptr ptr;
2163*c43e99fdSEd Maste 
2164*c43e99fdSEd Maste #define tt_iov_eq(v, s)						\
2165*c43e99fdSEd Maste 	tt_int_op((v)->iov_len, ==, strlen(s));			\
2166*c43e99fdSEd Maste 	tt_assert(!memcmp((v)->iov_base, (s), strlen(s)))
2167*c43e99fdSEd Maste 
2168*c43e99fdSEd Maste 	/* Let's make a very fragmented buffer. */
2169*c43e99fdSEd Maste 	buf = evbuffer_new();
2170*c43e99fdSEd Maste 	tmp_buf = evbuffer_new();
2171*c43e99fdSEd Maste 	for (i = 0; i < 16; ++i) {
2172*c43e99fdSEd Maste 		evbuffer_add_printf(tmp_buf, "Contents of chunk [%d]\n", i);
2173*c43e99fdSEd Maste 		evbuffer_add_buffer(buf, tmp_buf);
2174*c43e99fdSEd Maste 	}
2175*c43e99fdSEd Maste 
2176*c43e99fdSEd Maste 	/* How many chunks do we need for everything? */
2177*c43e99fdSEd Maste 	i = evbuffer_peek(buf, -1, NULL, NULL, 0);
2178*c43e99fdSEd Maste 	tt_int_op(i, ==, 16);
2179*c43e99fdSEd Maste 
2180*c43e99fdSEd Maste 	/* Simple peek: get everything. */
2181*c43e99fdSEd Maste 	i = evbuffer_peek(buf, -1, NULL, v, 20);
2182*c43e99fdSEd Maste 	tt_int_op(i, ==, 16); /* we used only 16 chunks. */
2183*c43e99fdSEd Maste 	tt_iov_eq(&v[0], "Contents of chunk [0]\n");
2184*c43e99fdSEd Maste 	tt_iov_eq(&v[3], "Contents of chunk [3]\n");
2185*c43e99fdSEd Maste 	tt_iov_eq(&v[12], "Contents of chunk [12]\n");
2186*c43e99fdSEd Maste 	tt_iov_eq(&v[15], "Contents of chunk [15]\n");
2187*c43e99fdSEd Maste 
2188*c43e99fdSEd Maste 	/* Just get one chunk worth. */
2189*c43e99fdSEd Maste 	memset(v, 0, sizeof(v));
2190*c43e99fdSEd Maste 	i = evbuffer_peek(buf, -1, NULL, v, 1);
2191*c43e99fdSEd Maste 	tt_int_op(i, ==, 1);
2192*c43e99fdSEd Maste 	tt_iov_eq(&v[0], "Contents of chunk [0]\n");
2193*c43e99fdSEd Maste 	tt_assert(v[1].iov_base == NULL);
2194*c43e99fdSEd Maste 
2195*c43e99fdSEd Maste 	/* Suppose we want at least the first 40 bytes. */
2196*c43e99fdSEd Maste 	memset(v, 0, sizeof(v));
2197*c43e99fdSEd Maste 	i = evbuffer_peek(buf, 40, NULL, v, 16);
2198*c43e99fdSEd Maste 	tt_int_op(i, ==, 2);
2199*c43e99fdSEd Maste 	tt_iov_eq(&v[0], "Contents of chunk [0]\n");
2200*c43e99fdSEd Maste 	tt_iov_eq(&v[1], "Contents of chunk [1]\n");
2201*c43e99fdSEd Maste 	tt_assert(v[2].iov_base == NULL);
2202*c43e99fdSEd Maste 
2203*c43e99fdSEd Maste 	/* How many chunks do we need for 100 bytes? */
2204*c43e99fdSEd Maste 	memset(v, 0, sizeof(v));
2205*c43e99fdSEd Maste 	i = evbuffer_peek(buf, 100, NULL, NULL, 0);
2206*c43e99fdSEd Maste 	tt_int_op(i, ==, 5);
2207*c43e99fdSEd Maste 	tt_assert(v[0].iov_base == NULL);
2208*c43e99fdSEd Maste 
2209*c43e99fdSEd Maste 	/* Now we ask for more bytes than we provide chunks for */
2210*c43e99fdSEd Maste 	memset(v, 0, sizeof(v));
2211*c43e99fdSEd Maste 	i = evbuffer_peek(buf, 60, NULL, v, 1);
2212*c43e99fdSEd Maste 	tt_int_op(i, ==, 3);
2213*c43e99fdSEd Maste 	tt_iov_eq(&v[0], "Contents of chunk [0]\n");
2214*c43e99fdSEd Maste 	tt_assert(v[1].iov_base == NULL);
2215*c43e99fdSEd Maste 
2216*c43e99fdSEd Maste 	/* Now we ask for more bytes than the buffer has. */
2217*c43e99fdSEd Maste 	memset(v, 0, sizeof(v));
2218*c43e99fdSEd Maste 	i = evbuffer_peek(buf, 65536, NULL, v, 20);
2219*c43e99fdSEd Maste 	tt_int_op(i, ==, 16); /* we used only 16 chunks. */
2220*c43e99fdSEd Maste 	tt_iov_eq(&v[0], "Contents of chunk [0]\n");
2221*c43e99fdSEd Maste 	tt_iov_eq(&v[3], "Contents of chunk [3]\n");
2222*c43e99fdSEd Maste 	tt_iov_eq(&v[12], "Contents of chunk [12]\n");
2223*c43e99fdSEd Maste 	tt_iov_eq(&v[15], "Contents of chunk [15]\n");
2224*c43e99fdSEd Maste 	tt_assert(v[16].iov_base == NULL);
2225*c43e99fdSEd Maste 
2226*c43e99fdSEd Maste 	/* What happens if we try an empty buffer? */
2227*c43e99fdSEd Maste 	memset(v, 0, sizeof(v));
2228*c43e99fdSEd Maste 	i = evbuffer_peek(tmp_buf, -1, NULL, v, 20);
2229*c43e99fdSEd Maste 	tt_int_op(i, ==, 0);
2230*c43e99fdSEd Maste 	tt_assert(v[0].iov_base == NULL);
2231*c43e99fdSEd Maste 	memset(v, 0, sizeof(v));
2232*c43e99fdSEd Maste 	i = evbuffer_peek(tmp_buf, 50, NULL, v, 20);
2233*c43e99fdSEd Maste 	tt_int_op(i, ==, 0);
2234*c43e99fdSEd Maste 	tt_assert(v[0].iov_base == NULL);
2235*c43e99fdSEd Maste 
2236*c43e99fdSEd Maste 	/* Okay, now time to have fun with pointers. */
2237*c43e99fdSEd Maste 	memset(v, 0, sizeof(v));
2238*c43e99fdSEd Maste 	evbuffer_ptr_set(buf, &ptr, 30, EVBUFFER_PTR_SET);
2239*c43e99fdSEd Maste 	i = evbuffer_peek(buf, 50, &ptr, v, 20);
2240*c43e99fdSEd Maste 	tt_int_op(i, ==, 3);
2241*c43e99fdSEd Maste 	tt_iov_eq(&v[0], " of chunk [1]\n");
2242*c43e99fdSEd Maste 	tt_iov_eq(&v[1], "Contents of chunk [2]\n");
2243*c43e99fdSEd Maste 	tt_iov_eq(&v[2], "Contents of chunk [3]\n"); /*more than we asked for*/
2244*c43e99fdSEd Maste 
2245*c43e99fdSEd Maste 	/* advance to the start of another chain. */
2246*c43e99fdSEd Maste 	memset(v, 0, sizeof(v));
2247*c43e99fdSEd Maste 	evbuffer_ptr_set(buf, &ptr, 14, EVBUFFER_PTR_ADD);
2248*c43e99fdSEd Maste 	i = evbuffer_peek(buf, 44, &ptr, v, 20);
2249*c43e99fdSEd Maste 	tt_int_op(i, ==, 2);
2250*c43e99fdSEd Maste 	tt_iov_eq(&v[0], "Contents of chunk [2]\n");
2251*c43e99fdSEd Maste 	tt_iov_eq(&v[1], "Contents of chunk [3]\n"); /*more than we asked for*/
2252*c43e99fdSEd Maste 
2253*c43e99fdSEd Maste 	/* peek at the end of the buffer */
2254*c43e99fdSEd Maste 	memset(v, 0, sizeof(v));
2255*c43e99fdSEd Maste 	tt_assert(evbuffer_ptr_set(buf, &ptr, evbuffer_get_length(buf), EVBUFFER_PTR_SET) == 0);
2256*c43e99fdSEd Maste 	i = evbuffer_peek(buf, 44, &ptr, v, 20);
2257*c43e99fdSEd Maste 	tt_int_op(i, ==, 0);
2258*c43e99fdSEd Maste 	tt_assert(v[0].iov_base == NULL);
2259*c43e99fdSEd Maste 
2260*c43e99fdSEd Maste end:
2261*c43e99fdSEd Maste 	if (buf)
2262*c43e99fdSEd Maste 		evbuffer_free(buf);
2263*c43e99fdSEd Maste 	if (tmp_buf)
2264*c43e99fdSEd Maste 		evbuffer_free(tmp_buf);
2265*c43e99fdSEd Maste }
2266*c43e99fdSEd Maste 
2267*c43e99fdSEd Maste /* Check whether evbuffer freezing works right.  This is called twice,
2268*c43e99fdSEd Maste    once with the argument "start" and once with the argument "end".
2269*c43e99fdSEd Maste    When we test "start", we freeze the start of an evbuffer and make sure
2270*c43e99fdSEd Maste    that modifying the start of the buffer doesn't work.  When we test
2271*c43e99fdSEd Maste    "end", we freeze the end of an evbuffer and make sure that modifying
2272*c43e99fdSEd Maste    the end of the buffer doesn't work.
2273*c43e99fdSEd Maste  */
2274*c43e99fdSEd Maste static void
2275*c43e99fdSEd Maste test_evbuffer_freeze(void *ptr)
2276*c43e99fdSEd Maste {
2277*c43e99fdSEd Maste 	struct evbuffer *buf = NULL, *tmp_buf=NULL;
2278*c43e99fdSEd Maste 	const char string[] = /* Year's End, Richard Wilbur */
2279*c43e99fdSEd Maste 	    "I've known the wind by water banks to shake\n"
2280*c43e99fdSEd Maste 	    "The late leaves down, which frozen where they fell\n"
2281*c43e99fdSEd Maste 	    "And held in ice as dancers in a spell\n"
2282*c43e99fdSEd Maste 	    "Fluttered all winter long into a lake...";
2283*c43e99fdSEd Maste 	const int start = !strcmp(ptr, "start");
2284*c43e99fdSEd Maste 	char *cp;
2285*c43e99fdSEd Maste 	char charbuf[128];
2286*c43e99fdSEd Maste 	int r;
2287*c43e99fdSEd Maste 	size_t orig_length;
2288*c43e99fdSEd Maste 	struct evbuffer_iovec v[1];
2289*c43e99fdSEd Maste 
2290*c43e99fdSEd Maste 	if (!start)
2291*c43e99fdSEd Maste 		tt_str_op(ptr, ==, "end");
2292*c43e99fdSEd Maste 
2293*c43e99fdSEd Maste 	buf = evbuffer_new();
2294*c43e99fdSEd Maste 	tmp_buf = evbuffer_new();
2295*c43e99fdSEd Maste 	tt_assert(tmp_buf);
2296*c43e99fdSEd Maste 
2297*c43e99fdSEd Maste 	evbuffer_add(buf, string, strlen(string));
2298*c43e99fdSEd Maste 	evbuffer_freeze(buf, start); /* Freeze the start or the end.*/
2299*c43e99fdSEd Maste 
2300*c43e99fdSEd Maste #define FREEZE_EQ(a, startcase, endcase)		\
2301*c43e99fdSEd Maste 	do {						\
2302*c43e99fdSEd Maste 	    if (start) {				\
2303*c43e99fdSEd Maste 		    tt_int_op((a), ==, (startcase));	\
2304*c43e99fdSEd Maste 	    } else {					\
2305*c43e99fdSEd Maste 		    tt_int_op((a), ==, (endcase));	\
2306*c43e99fdSEd Maste 	    }						\
2307*c43e99fdSEd Maste 	} while (0)
2308*c43e99fdSEd Maste 
2309*c43e99fdSEd Maste 
2310*c43e99fdSEd Maste 	orig_length = evbuffer_get_length(buf);
2311*c43e99fdSEd Maste 
2312*c43e99fdSEd Maste 	/* These functions all manipulate the end of buf. */
2313*c43e99fdSEd Maste 	r = evbuffer_add(buf, "abc", 0);
2314*c43e99fdSEd Maste 	FREEZE_EQ(r, 0, -1);
2315*c43e99fdSEd Maste 	r = evbuffer_reserve_space(buf, 10, v, 1);
2316*c43e99fdSEd Maste 	FREEZE_EQ(r, 1, -1);
2317*c43e99fdSEd Maste 	if (r == 1) {
2318*c43e99fdSEd Maste 		memset(v[0].iov_base, 'X', 10);
2319*c43e99fdSEd Maste 		v[0].iov_len = 10;
2320*c43e99fdSEd Maste 	}
2321*c43e99fdSEd Maste 	r = evbuffer_commit_space(buf, v, 1);
2322*c43e99fdSEd Maste 	FREEZE_EQ(r, 0, -1);
2323*c43e99fdSEd Maste 	r = evbuffer_add_reference(buf, string, 5, NULL, NULL);
2324*c43e99fdSEd Maste 	FREEZE_EQ(r, 0, -1);
2325*c43e99fdSEd Maste 	r = evbuffer_add_printf(buf, "Hello %s", "world");
2326*c43e99fdSEd Maste 	FREEZE_EQ(r, 11, -1);
2327*c43e99fdSEd Maste 	/* TODO: test add_buffer, add_file, read */
2328*c43e99fdSEd Maste 
2329*c43e99fdSEd Maste 	if (!start)
2330*c43e99fdSEd Maste 		tt_int_op(orig_length, ==, evbuffer_get_length(buf));
2331*c43e99fdSEd Maste 
2332*c43e99fdSEd Maste 	orig_length = evbuffer_get_length(buf);
2333*c43e99fdSEd Maste 
2334*c43e99fdSEd Maste 	/* These functions all manipulate the start of buf. */
2335*c43e99fdSEd Maste 	r = evbuffer_remove(buf, charbuf, 1);
2336*c43e99fdSEd Maste 	FREEZE_EQ(r, -1, 1);
2337*c43e99fdSEd Maste 	r = evbuffer_drain(buf, 3);
2338*c43e99fdSEd Maste 	FREEZE_EQ(r, -1, 0);
2339*c43e99fdSEd Maste 	r = evbuffer_prepend(buf, "dummy", 5);
2340*c43e99fdSEd Maste 	FREEZE_EQ(r, -1, 0);
2341*c43e99fdSEd Maste 	cp = evbuffer_readln(buf, NULL, EVBUFFER_EOL_LF);
2342*c43e99fdSEd Maste 	FREEZE_EQ(cp==NULL, 1, 0);
2343*c43e99fdSEd Maste 	if (cp)
2344*c43e99fdSEd Maste 		free(cp);
2345*c43e99fdSEd Maste 	/* TODO: Test remove_buffer, add_buffer, write, prepend_buffer */
2346*c43e99fdSEd Maste 
2347*c43e99fdSEd Maste 	if (start)
2348*c43e99fdSEd Maste 		tt_int_op(orig_length, ==, evbuffer_get_length(buf));
2349*c43e99fdSEd Maste 
2350*c43e99fdSEd Maste end:
2351*c43e99fdSEd Maste 	if (buf)
2352*c43e99fdSEd Maste 		evbuffer_free(buf);
2353*c43e99fdSEd Maste 
2354*c43e99fdSEd Maste 	if (tmp_buf)
2355*c43e99fdSEd Maste 		evbuffer_free(tmp_buf);
2356*c43e99fdSEd Maste }
2357*c43e99fdSEd Maste 
2358*c43e99fdSEd Maste static void
2359*c43e99fdSEd Maste test_evbuffer_add_iovec(void * ptr)
2360*c43e99fdSEd Maste {
2361*c43e99fdSEd Maste 	struct evbuffer * buf = NULL;
2362*c43e99fdSEd Maste 	struct evbuffer_iovec vec[4];
2363*c43e99fdSEd Maste 	const char * data[] = {
2364*c43e99fdSEd Maste 		"Guilt resembles a sword with two edges.",
2365*c43e99fdSEd Maste 		"On the one hand, it cuts for Justice, imposing practical morality upon those who fear it.",
2366*c43e99fdSEd Maste 		"Conscience does not always adhere to rational judgment.",
2367*c43e99fdSEd Maste 		"Guilt is always a self-imposed burden, but it is not always rightly imposed."
2368*c43e99fdSEd Maste 		/* -- R.A. Salvatore, _Sojurn_ */
2369*c43e99fdSEd Maste 	};
2370*c43e99fdSEd Maste 	size_t expected_length = 0;
2371*c43e99fdSEd Maste 	size_t returned_length = 0;
2372*c43e99fdSEd Maste 	int i;
2373*c43e99fdSEd Maste 
2374*c43e99fdSEd Maste 	buf = evbuffer_new();
2375*c43e99fdSEd Maste 
2376*c43e99fdSEd Maste 	tt_assert(buf);
2377*c43e99fdSEd Maste 
2378*c43e99fdSEd Maste 	for (i = 0; i < 4; i++) {
2379*c43e99fdSEd Maste 		vec[i].iov_len  = strlen(data[i]);
2380*c43e99fdSEd Maste 		vec[i].iov_base = (char*) data[i];
2381*c43e99fdSEd Maste 		expected_length += vec[i].iov_len;
2382*c43e99fdSEd Maste 	}
2383*c43e99fdSEd Maste 
2384*c43e99fdSEd Maste 	returned_length = evbuffer_add_iovec(buf, vec, 4);
2385*c43e99fdSEd Maste 
2386*c43e99fdSEd Maste 	tt_int_op(returned_length, ==, evbuffer_get_length(buf));
2387*c43e99fdSEd Maste 	tt_int_op(evbuffer_get_length(buf), ==, expected_length);
2388*c43e99fdSEd Maste 
2389*c43e99fdSEd Maste 	for (i = 0; i < 4; i++) {
2390*c43e99fdSEd Maste 		char charbuf[1024];
2391*c43e99fdSEd Maste 
2392*c43e99fdSEd Maste 		memset(charbuf, 0, 1024);
2393*c43e99fdSEd Maste 		evbuffer_remove(buf, charbuf, strlen(data[i]));
2394*c43e99fdSEd Maste 		tt_assert(strcmp(charbuf, data[i]) == 0);
2395*c43e99fdSEd Maste 	}
2396*c43e99fdSEd Maste 
2397*c43e99fdSEd Maste 	tt_assert(evbuffer_get_length(buf) == 0);
2398*c43e99fdSEd Maste end:
2399*c43e99fdSEd Maste 	if (buf) {
2400*c43e99fdSEd Maste 		evbuffer_free(buf);
2401*c43e99fdSEd Maste 	}
2402*c43e99fdSEd Maste }
2403*c43e99fdSEd Maste 
2404*c43e99fdSEd Maste static void
2405*c43e99fdSEd Maste test_evbuffer_copyout(void *dummy)
2406*c43e99fdSEd Maste {
2407*c43e99fdSEd Maste 	const char string[] =
2408*c43e99fdSEd Maste 	    "Still they skirmish to and fro, men my messmates on the snow "
2409*c43e99fdSEd Maste 	    "When we headed off the aurochs turn for turn; "
2410*c43e99fdSEd Maste 	    "When the rich Allobrogenses never kept amanuenses, "
2411*c43e99fdSEd Maste 	    "And our only plots were piled in lakes at Berne.";
2412*c43e99fdSEd Maste 	/* -- Kipling, "In The Neolithic Age" */
2413*c43e99fdSEd Maste 	char tmp[1024];
2414*c43e99fdSEd Maste 	struct evbuffer_ptr ptr;
2415*c43e99fdSEd Maste 	struct evbuffer *buf;
2416*c43e99fdSEd Maste 
2417*c43e99fdSEd Maste 	(void)dummy;
2418*c43e99fdSEd Maste 
2419*c43e99fdSEd Maste 	buf = evbuffer_new();
2420*c43e99fdSEd Maste 	tt_assert(buf);
2421*c43e99fdSEd Maste 
2422*c43e99fdSEd Maste 	tt_int_op(strlen(string), ==, 206);
2423*c43e99fdSEd Maste 
2424*c43e99fdSEd Maste 	/* Ensure separate chains */
2425*c43e99fdSEd Maste 	evbuffer_add_reference(buf, string, 80, no_cleanup, NULL);
2426*c43e99fdSEd Maste 	evbuffer_add_reference(buf, string+80, 80, no_cleanup, NULL);
2427*c43e99fdSEd Maste 	evbuffer_add(buf, string+160, strlen(string)-160);
2428*c43e99fdSEd Maste 
2429*c43e99fdSEd Maste 	tt_int_op(206, ==, evbuffer_get_length(buf));
2430*c43e99fdSEd Maste 
2431*c43e99fdSEd Maste 	/* First, let's test plain old copyout. */
2432*c43e99fdSEd Maste 
2433*c43e99fdSEd Maste 	/* Copy a little from the beginning. */
2434*c43e99fdSEd Maste 	tt_int_op(10, ==, evbuffer_copyout(buf, tmp, 10));
2435*c43e99fdSEd Maste 	tt_int_op(0, ==, memcmp(tmp, "Still they", 10));
2436*c43e99fdSEd Maste 
2437*c43e99fdSEd Maste 	/* Now copy more than a little from the beginning */
2438*c43e99fdSEd Maste 	memset(tmp, 0, sizeof(tmp));
2439*c43e99fdSEd Maste 	tt_int_op(100, ==, evbuffer_copyout(buf, tmp, 100));
2440*c43e99fdSEd Maste 	tt_int_op(0, ==, memcmp(tmp, string, 100));
2441*c43e99fdSEd Maste 
2442*c43e99fdSEd Maste 	/* Copy too much; ensure truncation. */
2443*c43e99fdSEd Maste 	memset(tmp, 0, sizeof(tmp));
2444*c43e99fdSEd Maste 	tt_int_op(206, ==, evbuffer_copyout(buf, tmp, 230));
2445*c43e99fdSEd Maste 	tt_int_op(0, ==, memcmp(tmp, string, 206));
2446*c43e99fdSEd Maste 
2447*c43e99fdSEd Maste 	/* That was supposed to be nondestructive, btw */
2448*c43e99fdSEd Maste 	tt_int_op(206, ==, evbuffer_get_length(buf));
2449*c43e99fdSEd Maste 
2450*c43e99fdSEd Maste 	/* Now it's time to test copyout_from!  First, let's start in the
2451*c43e99fdSEd Maste 	 * first chain. */
2452*c43e99fdSEd Maste 	evbuffer_ptr_set(buf, &ptr, 15, EVBUFFER_PTR_SET);
2453*c43e99fdSEd Maste 	memset(tmp, 0, sizeof(tmp));
2454*c43e99fdSEd Maste 	tt_int_op(10, ==, evbuffer_copyout_from(buf, &ptr, tmp, 10));
2455*c43e99fdSEd Maste 	tt_int_op(0, ==, memcmp(tmp, "mish to an", 10));
2456*c43e99fdSEd Maste 
2457*c43e99fdSEd Maste 	/* Right up to the end of the first chain */
2458*c43e99fdSEd Maste 	memset(tmp, 0, sizeof(tmp));
2459*c43e99fdSEd Maste 	tt_int_op(65, ==, evbuffer_copyout_from(buf, &ptr, tmp, 65));
2460*c43e99fdSEd Maste 	tt_int_op(0, ==, memcmp(tmp, string+15, 65));
2461*c43e99fdSEd Maste 
2462*c43e99fdSEd Maste 	/* Span into the second chain */
2463*c43e99fdSEd Maste 	memset(tmp, 0, sizeof(tmp));
2464*c43e99fdSEd Maste 	tt_int_op(90, ==, evbuffer_copyout_from(buf, &ptr, tmp, 90));
2465*c43e99fdSEd Maste 	tt_int_op(0, ==, memcmp(tmp, string+15, 90));
2466*c43e99fdSEd Maste 
2467*c43e99fdSEd Maste 	/* Span into the third chain */
2468*c43e99fdSEd Maste 	memset(tmp, 0, sizeof(tmp));
2469*c43e99fdSEd Maste 	tt_int_op(160, ==, evbuffer_copyout_from(buf, &ptr, tmp, 160));
2470*c43e99fdSEd Maste 	tt_int_op(0, ==, memcmp(tmp, string+15, 160));
2471*c43e99fdSEd Maste 
2472*c43e99fdSEd Maste 	/* Overrun */
2473*c43e99fdSEd Maste 	memset(tmp, 0, sizeof(tmp));
2474*c43e99fdSEd Maste 	tt_int_op(206-15, ==, evbuffer_copyout_from(buf, &ptr, tmp, 999));
2475*c43e99fdSEd Maste 	tt_int_op(0, ==, memcmp(tmp, string+15, 206-15));
2476*c43e99fdSEd Maste 
2477*c43e99fdSEd Maste 	/* That was supposed to be nondestructive, too */
2478*c43e99fdSEd Maste 	tt_int_op(206, ==, evbuffer_get_length(buf));
2479*c43e99fdSEd Maste 
2480*c43e99fdSEd Maste end:
2481*c43e99fdSEd Maste 	if (buf)
2482*c43e99fdSEd Maste 		evbuffer_free(buf);
2483*c43e99fdSEd Maste }
2484*c43e99fdSEd Maste 
2485*c43e99fdSEd Maste static void *
2486*c43e99fdSEd Maste setup_passthrough(const struct testcase_t *testcase)
2487*c43e99fdSEd Maste {
2488*c43e99fdSEd Maste 	return testcase->setup_data;
2489*c43e99fdSEd Maste }
2490*c43e99fdSEd Maste static int
2491*c43e99fdSEd Maste cleanup_passthrough(const struct testcase_t *testcase, void *ptr)
2492*c43e99fdSEd Maste {
2493*c43e99fdSEd Maste 	(void) ptr;
2494*c43e99fdSEd Maste 	return 1;
2495*c43e99fdSEd Maste }
2496*c43e99fdSEd Maste 
2497*c43e99fdSEd Maste static const struct testcase_setup_t nil_setup = {
2498*c43e99fdSEd Maste 	setup_passthrough,
2499*c43e99fdSEd Maste 	cleanup_passthrough
2500*c43e99fdSEd Maste };
2501*c43e99fdSEd Maste 
2502*c43e99fdSEd Maste struct testcase_t evbuffer_testcases[] = {
2503*c43e99fdSEd Maste 	{ "evbuffer", test_evbuffer, 0, NULL, NULL },
2504*c43e99fdSEd Maste 	{ "remove_buffer_with_empty", test_evbuffer_remove_buffer_with_empty, 0, NULL, NULL },
2505*c43e99fdSEd Maste 	{ "remove_buffer_with_empty2", test_evbuffer_remove_buffer_with_empty2, 0, NULL, NULL },
2506*c43e99fdSEd Maste 	{ "remove_buffer_with_empty3", test_evbuffer_remove_buffer_with_empty3, 0, NULL, NULL },
2507*c43e99fdSEd Maste 	{ "add_buffer_with_empty", test_evbuffer_add_buffer_with_empty, 0, NULL, NULL },
2508*c43e99fdSEd Maste 	{ "add_buffer_with_empty2", test_evbuffer_add_buffer_with_empty2, 0, NULL, NULL },
2509*c43e99fdSEd Maste 	{ "reserve2", test_evbuffer_reserve2, 0, NULL, NULL },
2510*c43e99fdSEd Maste 	{ "reserve_many", test_evbuffer_reserve_many, 0, NULL, NULL },
2511*c43e99fdSEd Maste 	{ "reserve_many2", test_evbuffer_reserve_many, 0, &nil_setup, (void*)"add" },
2512*c43e99fdSEd Maste 	{ "reserve_many3", test_evbuffer_reserve_many, 0, &nil_setup, (void*)"fill" },
2513*c43e99fdSEd Maste 	{ "expand", test_evbuffer_expand, 0, NULL, NULL },
2514*c43e99fdSEd Maste 	{ "expand_overflow", test_evbuffer_expand_overflow, 0, NULL, NULL },
2515*c43e99fdSEd Maste 	{ "add1", test_evbuffer_add1, 0, NULL, NULL },
2516*c43e99fdSEd Maste 	{ "add2", test_evbuffer_add2, 0, NULL, NULL },
2517*c43e99fdSEd Maste 	{ "reference", test_evbuffer_reference, 0, NULL, NULL },
2518*c43e99fdSEd Maste 	{ "reference2", test_evbuffer_reference2, 0, NULL, NULL },
2519*c43e99fdSEd Maste 	{ "iterative", test_evbuffer_iterative, 0, NULL, NULL },
2520*c43e99fdSEd Maste 	{ "readln", test_evbuffer_readln, TT_NO_LOGS, &basic_setup, NULL },
2521*c43e99fdSEd Maste 	{ "search_eol", test_evbuffer_search_eol, 0, NULL, NULL },
2522*c43e99fdSEd Maste 	{ "find", test_evbuffer_find, 0, NULL, NULL },
2523*c43e99fdSEd Maste 	{ "ptr_set", test_evbuffer_ptr_set, 0, NULL, NULL },
2524*c43e99fdSEd Maste 	{ "search", test_evbuffer_search, 0, NULL, NULL },
2525*c43e99fdSEd Maste 	{ "callbacks", test_evbuffer_callbacks, 0, NULL, NULL },
2526*c43e99fdSEd Maste 	{ "add_reference", test_evbuffer_add_reference, 0, NULL, NULL },
2527*c43e99fdSEd Maste 	{ "multicast", test_evbuffer_multicast, 0, NULL, NULL },
2528*c43e99fdSEd Maste 	{ "multicast_drain", test_evbuffer_multicast_drain, 0, NULL, NULL },
2529*c43e99fdSEd Maste 	{ "prepend", test_evbuffer_prepend, TT_FORK, NULL, NULL },
2530*c43e99fdSEd Maste 	{ "peek", test_evbuffer_peek, 0, NULL, NULL },
2531*c43e99fdSEd Maste 	{ "peek_first_gt", test_evbuffer_peek_first_gt, 0, NULL, NULL },
2532*c43e99fdSEd Maste 	{ "freeze_start", test_evbuffer_freeze, 0, &nil_setup, (void*)"start" },
2533*c43e99fdSEd Maste 	{ "freeze_end", test_evbuffer_freeze, 0, &nil_setup, (void*)"end" },
2534*c43e99fdSEd Maste 	{ "add_iovec", test_evbuffer_add_iovec, 0, NULL, NULL},
2535*c43e99fdSEd Maste 	{ "copyout", test_evbuffer_copyout, 0, NULL, NULL},
2536*c43e99fdSEd Maste 	{ "file_segment_add_cleanup_cb", test_evbuffer_file_segment_add_cleanup_cb, 0, NULL, NULL },
2537*c43e99fdSEd Maste 
2538*c43e99fdSEd Maste #define ADDFILE_TEST(name, parameters)					\
2539*c43e99fdSEd Maste 	{ name, test_evbuffer_add_file, TT_FORK|TT_NEED_BASE,		\
2540*c43e99fdSEd Maste 	  &basic_setup, (void*)(parameters) }
2541*c43e99fdSEd Maste 
2542*c43e99fdSEd Maste #define ADDFILE_TEST_GROUP(name, parameters)			\
2543*c43e99fdSEd Maste 	ADDFILE_TEST(name "_sendfile", "sendfile " parameters), \
2544*c43e99fdSEd Maste 	ADDFILE_TEST(name "_mmap", "mmap " parameters),		\
2545*c43e99fdSEd Maste 	ADDFILE_TEST(name "_linear", "linear " parameters)
2546*c43e99fdSEd Maste 
2547*c43e99fdSEd Maste 	ADDFILE_TEST_GROUP("add_file", ""),
2548*c43e99fdSEd Maste 	ADDFILE_TEST("add_file_nosegment", "default nosegment"),
2549*c43e99fdSEd Maste 
2550*c43e99fdSEd Maste 	ADDFILE_TEST_GROUP("add_big_file", "bigfile"),
2551*c43e99fdSEd Maste 	ADDFILE_TEST("add_big_file_nosegment", "default nosegment bigfile"),
2552*c43e99fdSEd Maste 
2553*c43e99fdSEd Maste 	ADDFILE_TEST_GROUP("add_file_offset", "bigfile map_offset"),
2554*c43e99fdSEd Maste 	ADDFILE_TEST("add_file_offset_nosegment",
2555*c43e99fdSEd Maste 	    "default nosegment bigfile map_offset"),
2556*c43e99fdSEd Maste 
2557*c43e99fdSEd Maste 	ADDFILE_TEST_GROUP("add_file_offset2", "bigfile offset_in_segment"),
2558*c43e99fdSEd Maste 
2559*c43e99fdSEd Maste 	ADDFILE_TEST_GROUP("add_file_offset3",
2560*c43e99fdSEd Maste 	    "bigfile offset_in_segment map_offset"),
2561*c43e99fdSEd Maste 
2562*c43e99fdSEd Maste 	END_OF_TESTCASES
2563*c43e99fdSEd Maste };
2564