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