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