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