2 * Copyright (c) 2003-2007 Niels Provos <provos@citi.umich.edu>
3 * Copyright (c) 2007-2012 Niels Provos and Nick Mathewson
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. The name of the author may not be used to endorse or promote products
14 * derived from this software without specific prior written permission.
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
17 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
18 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
19 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
20 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
21 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
22 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
23 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
25 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 #include "util-internal.h"
34 #include "event2/event-config.h"
36 #include <sys/types.h>
38 #ifdef EVENT__HAVE_SYS_TIME_H
41 #include <sys/queue.h>
43 #include <sys/socket.h>
55 #include "event2/event.h"
56 #include "event2/buffer.h"
57 #include "event2/buffer_compat.h"
58 #include "event2/util.h"
60 #include "defer-internal.h"
61 #include "evbuffer-internal.h"
62 #include "log-internal.h"
66 #define ARRAY_SIZE(a) (sizeof(a) / sizeof(a[0]))
68 /* Validates that an evbuffer is good. Returns false if it isn't, true if it
71 evbuffer_validate_(struct evbuffer *buf)
73 struct evbuffer_chain *chain;
75 int found_last_with_datap = 0;
77 if (buf->first == NULL) {
78 tt_assert(buf->last == NULL);
79 tt_assert(buf->total_len == 0);
84 tt_assert(buf->last_with_datap);
85 if (buf->last_with_datap == &buf->first)
86 found_last_with_datap = 1;
88 while (chain != NULL) {
89 if (&chain->next == buf->last_with_datap)
90 found_last_with_datap = 1;
92 if (chain->next == NULL) {
93 tt_assert(buf->last == chain);
95 tt_assert(chain->buffer_len >= chain->misalign + chain->off);
100 tt_assert(*buf->last_with_datap);
102 if (*buf->last_with_datap) {
103 chain = *buf->last_with_datap;
104 if (chain->off == 0 || buf->total_len == 0) {
105 tt_assert(chain->off == 0)
106 tt_assert(chain == buf->first);
107 tt_assert(buf->total_len == 0);
110 while (chain != NULL) {
111 tt_assert(chain->off == 0);
115 tt_assert(buf->last_with_datap == &buf->first);
117 tt_assert(found_last_with_datap);
119 tt_assert(sum == buf->total_len);
126 evbuffer_get_waste(struct evbuffer *buf, size_t *allocatedp, size_t *wastedp, size_t *usedp)
128 struct evbuffer_chain *chain;
134 /* skip empty at start */
135 while (chain && chain->off==0) {
137 a += chain->buffer_len;
140 /* first nonempty chain: stuff at the end only is wasted. */
143 a += chain->buffer_len;
145 if (chain->next && chain->next->off)
146 w += (size_t)(chain->buffer_len - (chain->misalign + chain->off));
149 /* subsequent nonempty chains */
150 while (chain && chain->off) {
152 a += chain->buffer_len;
153 w += (size_t)chain->misalign;
155 if (chain->next && chain->next->off)
156 w += (size_t) (chain->buffer_len - (chain->misalign + chain->off));
159 /* subsequent empty chains */
162 a += chain->buffer_len;
169 #define evbuffer_validate(buf) \
170 TT_STMT_BEGIN if (!evbuffer_validate_(buf)) TT_DIE(("Buffer format invalid")); TT_STMT_END
173 test_evbuffer(void *ptr)
175 static char buffer[512], *tmp;
176 struct evbuffer *evb = evbuffer_new();
177 struct evbuffer *evb_two = evbuffer_new();
181 evbuffer_validate(evb);
182 evbuffer_add_printf(evb, "%s/%d", "hello", 1);
183 evbuffer_validate(evb);
185 tt_assert(evbuffer_get_length(evb) == 7);
186 tt_assert(!memcmp((char*)EVBUFFER_DATA(evb), "hello/1", 1));
188 evbuffer_add_buffer(evb, evb_two);
189 evbuffer_validate(evb);
191 evbuffer_drain(evb, strlen("hello/"));
192 evbuffer_validate(evb);
193 tt_assert(evbuffer_get_length(evb) == 1);
194 tt_assert(!memcmp((char*)EVBUFFER_DATA(evb), "1", 1));
196 evbuffer_add_printf(evb_two, "%s", "/hello");
197 evbuffer_validate(evb);
198 evbuffer_add_buffer(evb, evb_two);
199 evbuffer_validate(evb);
201 tt_assert(evbuffer_get_length(evb_two) == 0);
202 tt_assert(evbuffer_get_length(evb) == 7);
203 tt_assert(!memcmp((char*)EVBUFFER_DATA(evb), "1/hello", 7));
205 memset(buffer, 0, sizeof(buffer));
206 evbuffer_add(evb, buffer, sizeof(buffer));
207 evbuffer_validate(evb);
208 tt_assert(evbuffer_get_length(evb) == 7 + 512);
210 tmp = (char *)evbuffer_pullup(evb, 7 + 512);
212 tt_assert(!strncmp(tmp, "1/hello", 7));
213 tt_assert(!memcmp(tmp + 7, buffer, sizeof(buffer)));
214 evbuffer_validate(evb);
216 evbuffer_prepend(evb, "something", 9);
217 evbuffer_validate(evb);
218 evbuffer_prepend(evb, "else", 4);
219 evbuffer_validate(evb);
221 tmp = (char *)evbuffer_pullup(evb, 4 + 9 + 7);
222 tt_assert(!strncmp(tmp, "elsesomething1/hello", 4 + 9 + 7));
223 evbuffer_validate(evb);
225 evbuffer_drain(evb, -1);
226 evbuffer_validate(evb);
227 evbuffer_drain(evb_two, -1);
228 evbuffer_validate(evb);
230 for (i = 0; i < 3; ++i) {
231 evbuffer_add(evb_two, buffer, sizeof(buffer));
232 evbuffer_validate(evb_two);
233 evbuffer_add_buffer(evb, evb_two);
234 evbuffer_validate(evb);
235 evbuffer_validate(evb_two);
238 tt_assert(evbuffer_get_length(evb_two) == 0);
239 tt_assert(evbuffer_get_length(evb) == i * sizeof(buffer));
241 /* test remove buffer */
242 sz_tmp = (size_t)(sizeof(buffer)*2.5);
243 evbuffer_remove_buffer(evb, evb_two, sz_tmp);
244 tt_assert(evbuffer_get_length(evb_two) == sz_tmp);
245 tt_assert(evbuffer_get_length(evb) == sizeof(buffer) / 2);
246 evbuffer_validate(evb);
248 if (memcmp(evbuffer_pullup(
249 evb, -1), buffer, sizeof(buffer) / 2) != 0 ||
250 memcmp(evbuffer_pullup(
251 evb_two, -1), buffer, sizeof(buffer)) != 0)
252 tt_abort_msg("Pullup did not preserve content");
254 evbuffer_validate(evb);
257 /* testing one-vector reserve and commit */
259 struct evbuffer_iovec v[1];
263 for (i = 0; i < 3; ++i) {
264 r = evbuffer_reserve_space(evb, 10000, v, 1);
266 tt_assert(v[0].iov_len >= 10000);
267 tt_assert(v[0].iov_base != NULL);
269 evbuffer_validate(evb);
271 for (j = 0; j < 10000; ++j) {
274 evbuffer_validate(evb);
276 tt_int_op(evbuffer_commit_space(evb, v, 1), ==, 0);
277 evbuffer_validate(evb);
279 tt_assert(evbuffer_get_length(evb) >= 10000);
281 evbuffer_drain(evb, j * 5000);
282 evbuffer_validate(evb);
288 evbuffer_free(evb_two);
292 no_cleanup(const void *data, size_t datalen, void *extra)
297 test_evbuffer_remove_buffer_with_empty(void *ptr)
299 struct evbuffer *src = evbuffer_new();
300 struct evbuffer *dst = evbuffer_new();
301 char buf[2] = { 'A', 'A' };
303 evbuffer_validate(src);
304 evbuffer_validate(dst);
306 /* setup the buffers */
307 /* we need more data in src than we will move later */
308 evbuffer_add_reference(src, buf, sizeof(buf), no_cleanup, NULL);
309 evbuffer_add_reference(src, buf, sizeof(buf), no_cleanup, NULL);
310 /* we need one buffer in dst and one empty buffer at the end */
311 evbuffer_add(dst, buf, sizeof(buf));
312 evbuffer_add_reference(dst, buf, 0, no_cleanup, NULL);
314 evbuffer_validate(src);
315 evbuffer_validate(dst);
317 tt_mem_op(evbuffer_pullup(src, -1), ==, "AAAA", 4);
318 tt_mem_op(evbuffer_pullup(dst, -1), ==, "AA", 2);
320 /* move three bytes over */
321 evbuffer_remove_buffer(src, dst, 3);
323 evbuffer_validate(src);
324 evbuffer_validate(dst);
326 tt_mem_op(evbuffer_pullup(src, -1), ==, "A", 1);
327 tt_mem_op(evbuffer_pullup(dst, -1), ==, "AAAAA", 5);
335 test_evbuffer_remove_buffer_with_empty2(void *ptr)
337 struct evbuffer *src = evbuffer_new();
338 struct evbuffer *dst = evbuffer_new();
339 struct evbuffer *buf = evbuffer_new();
341 evbuffer_add(buf, "foo", 3);
342 evbuffer_add_reference(buf, "foo", 3, NULL, NULL);
344 evbuffer_add_reference(src, "foo", 3, NULL, NULL);
345 evbuffer_add_reference(src, NULL, 0, NULL, NULL);
346 evbuffer_add_buffer(src, buf);
348 evbuffer_add(buf, "foo", 3);
349 evbuffer_add_reference(buf, "foo", 3, NULL, NULL);
351 evbuffer_add_reference(dst, "foo", 3, NULL, NULL);
352 evbuffer_add_reference(dst, NULL, 0, NULL, NULL);
353 evbuffer_add_buffer(dst, buf);
355 tt_int_op(evbuffer_get_length(src), ==, 9);
356 tt_int_op(evbuffer_get_length(dst), ==, 9);
358 evbuffer_validate(src);
359 evbuffer_validate(dst);
361 tt_mem_op(evbuffer_pullup(src, -1), ==, "foofoofoo", 9);
362 tt_mem_op(evbuffer_pullup(dst, -1), ==, "foofoofoo", 9);
364 evbuffer_remove_buffer(src, dst, 8);
366 evbuffer_validate(src);
367 evbuffer_validate(dst);
369 tt_int_op(evbuffer_get_length(src), ==, 1);
370 tt_int_op(evbuffer_get_length(dst), ==, 17);
372 tt_mem_op(evbuffer_pullup(src, -1), ==, "o", 1);
373 tt_mem_op(evbuffer_pullup(dst, -1), ==, "foofoofoofoofoofo", 17);
382 test_evbuffer_remove_buffer_with_empty3(void *ptr)
384 struct evbuffer *src = evbuffer_new();
385 struct evbuffer *dst = evbuffer_new();
386 struct evbuffer *buf = evbuffer_new();
388 evbuffer_add(buf, "foo", 3);
389 evbuffer_add_reference(buf, NULL, 0, NULL, NULL);
391 evbuffer_add_reference(src, "foo", 3, NULL, NULL);
392 evbuffer_add_reference(src, NULL, 0, NULL, NULL);
393 evbuffer_prepend_buffer(src, buf);
395 evbuffer_add(buf, "foo", 3);
396 evbuffer_add_reference(buf, NULL, 0, NULL, NULL);
398 evbuffer_add_reference(dst, "foo", 3, NULL, NULL);
399 evbuffer_add_reference(dst, NULL, 0, NULL, NULL);
400 evbuffer_prepend_buffer(dst, buf);
402 tt_int_op(evbuffer_get_length(src), ==, 6);
403 tt_int_op(evbuffer_get_length(dst), ==, 6);
405 evbuffer_validate(src);
406 evbuffer_validate(dst);
408 tt_mem_op(evbuffer_pullup(src, -1), ==, "foofoo", 6);
409 tt_mem_op(evbuffer_pullup(dst, -1), ==, "foofoo", 6);
411 evbuffer_remove_buffer(src, dst, 5);
413 evbuffer_validate(src);
414 evbuffer_validate(dst);
416 tt_int_op(evbuffer_get_length(src), ==, 1);
417 tt_int_op(evbuffer_get_length(dst), ==, 11);
419 tt_mem_op(evbuffer_pullup(src, -1), ==, "o", 1);
420 tt_mem_op(evbuffer_pullup(dst, -1), ==, "foofoofoofo", 11);
429 test_evbuffer_pullup_with_empty(void *ptr)
431 struct evbuffer *buf = NULL;
433 buf = evbuffer_new();
434 evbuffer_add(buf, "foo", 3);
435 evbuffer_add_reference(buf, NULL, 0, NULL, NULL);
436 evbuffer_validate(buf);
437 tt_int_op(evbuffer_get_length(buf), ==, 3);
438 tt_mem_op(evbuffer_pullup(buf, -1), ==, "foo", 3);
441 buf = evbuffer_new();
442 evbuffer_validate(buf);
443 tt_int_op(evbuffer_get_length(buf), ==, 0);
444 tt_int_op(evbuffer_pullup(buf, -1), ==, NULL);
447 buf = evbuffer_new();
448 evbuffer_add(buf, "foo", 3);
449 evbuffer_add_reference(buf, NULL, 0, NULL, NULL);
450 evbuffer_validate(buf);
451 tt_mem_op(evbuffer_pullup(buf, 3), ==, "foo", 3);
459 test_evbuffer_remove_buffer_with_empty_front(void *ptr)
461 struct evbuffer *buf1 = NULL, *buf2 = NULL;
463 buf1 = evbuffer_new();
466 buf2 = evbuffer_new();
469 tt_int_op(evbuffer_add_reference(buf1, "foo", 3, NULL, NULL), ==, 0);
470 tt_int_op(evbuffer_prepend(buf1, "", 0), ==, 0);
471 tt_int_op(evbuffer_remove_buffer(buf1, buf2, 1), ==, 1);
472 tt_int_op(evbuffer_add(buf1, "bar", 3), ==, 0);
473 tt_mem_op(evbuffer_pullup(buf1, -1), ==, "oobar", 5);
475 evbuffer_validate(buf1);
476 evbuffer_validate(buf2);
486 test_evbuffer_remove_buffer_adjust_last_with_datap_with_empty(void *ptr)
488 struct evbuffer *buf1 = NULL, *buf2 = NULL;
490 buf1 = evbuffer_new();
493 buf2 = evbuffer_new();
496 tt_int_op(evbuffer_add(buf1, "aaaaaa", 6), ==, 0);
501 struct evbuffer_iovec iovecs[2];
502 /** we want two chains, to leave one chain empty */
503 tt_int_op(evbuffer_reserve_space(buf1, 971, iovecs, 2), ==, 2);
504 tt_int_op(iovecs[0].iov_len, >=, 1);
505 tt_int_op(iovecs[1].iov_len, >=, 1);
506 tt_assert(*(char *)(iovecs[0].iov_base) = 'b');
507 tt_assert(iovecs[0].iov_len = 1);
508 tt_int_op(evbuffer_commit_space(buf1, iovecs, 1), ==, 0);
513 tt_int_op(evbuffer_add(buf2, "cc", 2), ==, 0);
514 tt_int_op(evbuffer_prepend(buf2, "ddd", 3), ==, 0);
517 // buf2: aaaaaabdddcc
518 tt_int_op(evbuffer_prepend_buffer(buf2, buf1), ==, 0);
520 // buf1: aaaaaabdddcc
522 tt_int_op(evbuffer_add_buffer(buf1, buf2), ==, 0);
526 tt_int_op(evbuffer_remove_buffer(buf1, buf2, 11), ==, 11);
528 // This fails today, we observe "aaaaaabcddd" instead!
529 tt_mem_op(evbuffer_pullup(buf2, -1), ==, "aaaaaabdddc", 11);
531 evbuffer_validate(buf1);
532 evbuffer_validate(buf2);
542 test_evbuffer_add_buffer_with_empty(void *ptr)
544 struct evbuffer *src = evbuffer_new();
545 struct evbuffer *dst = evbuffer_new();
546 struct evbuffer *buf = evbuffer_new();
548 evbuffer_add(buf, "foo", 3);
550 evbuffer_add_reference(src, "foo", 3, NULL, NULL);
551 evbuffer_add_reference(src, NULL, 0, NULL, NULL);
552 evbuffer_add_buffer(src, buf);
554 evbuffer_add(buf, "foo", 3);
556 evbuffer_add_reference(dst, "foo", 3, NULL, NULL);
557 evbuffer_add_reference(dst, NULL, 0, NULL, NULL);
558 evbuffer_add_buffer(dst, buf);
560 tt_int_op(evbuffer_get_length(src), ==, 6);
561 tt_int_op(evbuffer_get_length(dst), ==, 6);
563 evbuffer_validate(src);
564 evbuffer_validate(dst);
573 test_evbuffer_add_buffer_with_empty2(void *ptr)
575 struct evbuffer *src = evbuffer_new();
576 struct evbuffer *dst = evbuffer_new();
577 struct evbuffer *buf = evbuffer_new();
579 evbuffer_add(buf, "foo", 3);
581 evbuffer_add_reference(src, NULL, 0, NULL, NULL);
582 evbuffer_add_buffer(src, buf);
584 evbuffer_add(buf, "foo", 3);
586 evbuffer_add_reference(dst, NULL, 0, NULL, NULL);
587 evbuffer_add_buffer(dst, buf);
589 tt_int_op(evbuffer_get_length(src), ==, 3);
590 tt_int_op(evbuffer_get_length(dst), ==, 3);
592 evbuffer_validate(src);
593 evbuffer_validate(dst);
602 test_evbuffer_reserve2(void *ptr)
604 /* Test the two-vector cases of reserve/commit. */
605 struct evbuffer *buf = evbuffer_new();
607 struct evbuffer_iovec v[2];
611 /* First chunk will necessarily be one chunk. Use 512 bytes of it.*/
612 n = evbuffer_reserve_space(buf, 1024, v, 2);
614 tt_int_op(evbuffer_get_length(buf), ==, 0);
615 tt_assert(v[0].iov_base != NULL);
616 tt_int_op(v[0].iov_len, >=, 1024);
617 memset(v[0].iov_base, 'X', 512);
619 remaining = v[0].iov_len - 512;
621 evbuffer_validate(buf);
622 tt_int_op(0, ==, evbuffer_commit_space(buf, v, 1));
623 tt_int_op(evbuffer_get_length(buf), ==, 512);
624 evbuffer_validate(buf);
626 /* Ask for another same-chunk request, in an existing chunk. Use 8
628 n = evbuffer_reserve_space(buf, 32, v, 2);
630 tt_assert(cp + 512 == v[0].iov_base);
631 tt_int_op(remaining, ==, v[0].iov_len);
632 memset(v[0].iov_base, 'Y', 8);
634 tt_int_op(0, ==, evbuffer_commit_space(buf, v, 1));
635 tt_int_op(evbuffer_get_length(buf), ==, 520);
637 evbuffer_validate(buf);
639 /* Now ask for a request that will be split. Use only one byte of it,
641 n = evbuffer_reserve_space(buf, remaining+64, v, 2);
643 tt_assert(cp + 520 == v[0].iov_base);
644 tt_int_op(remaining, ==, v[0].iov_len);
645 tt_assert(v[1].iov_base);
646 tt_assert(v[1].iov_len >= 64);
648 memset(v[0].iov_base, 'Z', 1);
650 tt_int_op(0, ==, evbuffer_commit_space(buf, v, 1));
651 tt_int_op(evbuffer_get_length(buf), ==, 521);
653 evbuffer_validate(buf);
655 /* Now ask for a request that will be split. Use some of the first
656 * part and some of the second. */
657 n = evbuffer_reserve_space(buf, remaining+64, v, 2);
658 evbuffer_validate(buf);
660 tt_assert(cp + 521 == v[0].iov_base);
661 tt_int_op(remaining, ==, v[0].iov_len);
662 tt_assert(v[1].iov_base == cp2);
663 tt_assert(v[1].iov_len >= 64);
664 memset(v[0].iov_base, 'W', 400);
666 memset(v[1].iov_base, 'x', 60);
668 tt_int_op(0, ==, evbuffer_commit_space(buf, v, 2));
669 tt_int_op(evbuffer_get_length(buf), ==, 981);
670 evbuffer_validate(buf);
672 /* Now peek to make sure stuff got made how we like. */
673 memset(v,0,sizeof(v));
674 n = evbuffer_peek(buf, -1, NULL, v, 2);
676 tt_int_op(v[0].iov_len, ==, 921);
677 tt_int_op(v[1].iov_len, ==, 60);
680 for (i=0; i<512; ++i)
681 tt_int_op(cp[i], ==, 'X');
682 for (i=512; i<520; ++i)
683 tt_int_op(cp[i], ==, 'Y');
684 for (i=520; i<521; ++i)
685 tt_int_op(cp[i], ==, 'Z');
686 for (i=521; i<921; ++i)
687 tt_int_op(cp[i], ==, 'W');
691 tt_int_op(cp[i], ==, 'x');
698 test_evbuffer_reserve_many(void *ptr)
700 /* This is a glass-box test to handle expanding a buffer with more
701 * chunks and reallocating chunks as needed */
702 struct evbuffer *buf = evbuffer_new();
703 struct evbuffer_iovec v[8];
706 int add_data = ptr && !strcmp(ptr, "add");
707 int fill_first = ptr && !strcmp(ptr, "fill");
710 /* When reserving the the first chunk, we just allocate it */
711 n = evbuffer_reserve_space(buf, 128, v, 2);
712 evbuffer_validate(buf);
714 tt_assert(v[0].iov_len >= 128);
718 *(char*)v[0].iov_base = 'X';
720 n = evbuffer_commit_space(buf, v, 1);
722 } else if (fill_first) {
723 memset(v[0].iov_base, 'X', v[0].iov_len);
724 n = evbuffer_commit_space(buf, v, 1);
726 n = evbuffer_reserve_space(buf, 128, v, 2);
729 tt_assert(v[0].iov_base != cp1);
733 /* Make another chunk get added. */
734 n = evbuffer_reserve_space(buf, sz+128, v, 2);
735 evbuffer_validate(buf);
737 sz = v[0].iov_len + v[1].iov_len;
738 tt_int_op(sz, >=, v[0].iov_len+128);
740 tt_assert(v[0].iov_base == cp1 + 1);
742 tt_assert(v[0].iov_base == cp1);
747 /* And a third chunk. */
748 n = evbuffer_reserve_space(buf, sz+128, v, 3);
749 evbuffer_validate(buf);
751 tt_assert(cp1 == v[0].iov_base);
752 tt_assert(cp2 == v[1].iov_base);
753 sz = v[0].iov_len + v[1].iov_len + v[2].iov_len;
755 /* Now force a reallocation by asking for more space in only 2
757 n = evbuffer_reserve_space(buf, sz+128, v, 2);
758 evbuffer_validate(buf);
761 tt_assert(cp1 == v[0].iov_base);
771 test_evbuffer_reserve_with_empty(void *ptr)
773 struct evbuffer *buf;
774 struct evbuffer_iovec v[2];
776 tt_assert(buf = evbuffer_new());
777 evbuffer_add(buf, "a", 1);
778 tt_int_op(evbuffer_reserve_space(buf, 1<<12, v, 2), ==, 2);
780 *(char *)v[0].iov_base = 'b';
781 tt_int_op(evbuffer_commit_space(buf, v, 1), ==, 0);
782 evbuffer_add(buf, "c", 1);
783 tt_mem_op(evbuffer_pullup(buf, -1), ==, "abc", 2);
785 evbuffer_validate(buf);
792 /* regression for evbuffer_expand_fast_() with invalid last_with_datap that has
793 * been left after evbuffer_prepend() with empty chain in it */
795 test_evbuffer_reserve_invalid_last_with_datap(void *ptr)
797 struct evbuffer *buf = NULL;
798 struct evbuffer_iovec vec[2];
799 const int nvec = ARRAY_SIZE(vec);
802 buf = evbuffer_new();
805 /* prepend with an empty chain */
806 evbuffer_add_reference(buf, "", 0, NULL, NULL);
807 evbuffer_prepend(buf, "foo", 3);
808 /* after invalid last_with_datap will create new chain */
809 evbuffer_add(buf, "", 0);
810 /* we need to create at least 2 "used" (in evbuffer_expand_fast_()) chains */
811 tt_int_op(avec = evbuffer_reserve_space(buf, 1<<12, vec, nvec), >=, 1);
812 for (i = 0; i < avec; ++i)
814 tt_int_op(evbuffer_commit_space(buf, vec, avec), ==, 0);
816 /* and an actual problem, that triggers an assert(chain == buf->first) in
817 * evbuffer_expand_fast_() */
818 tt_int_op(evbuffer_reserve_space(buf, 1<<13, vec, nvec), >=, 1);
820 evbuffer_validate(buf);
828 test_evbuffer_expand(void *ptr)
831 struct evbuffer *buf;
835 memset(data, 'X', sizeof(data));
837 /* Make sure that expand() works on an empty buffer */
838 buf = evbuffer_new();
839 tt_int_op(evbuffer_expand(buf, 20000), ==, 0);
840 evbuffer_validate(buf);
842 evbuffer_get_waste(buf, &a,&w,&u);
845 tt_assert(a >= 20000);
846 tt_assert(buf->first);
847 tt_assert(buf->first == buf->last);
848 tt_assert(buf->first->off == 0);
849 tt_assert(buf->first->buffer_len >= 20000);
851 /* Make sure that expand() works as a no-op when there's enough
852 * contiguous space already. */
853 buffer = buf->first->buffer;
854 evbuffer_add(buf, data, 1024);
855 tt_int_op(evbuffer_expand(buf, 1024), ==, 0);
856 tt_assert(buf->first->buffer == buffer);
857 evbuffer_validate(buf);
860 /* Make sure that expand() can work by moving misaligned data
861 * when it makes sense to do so. */
862 buf = evbuffer_new();
863 evbuffer_add(buf, data, 400);
865 int n = (int)(buf->first->buffer_len - buf->first->off - 1);
866 tt_assert(n < (int)sizeof(data));
867 evbuffer_add(buf, data, n);
869 tt_assert(buf->first == buf->last);
870 tt_assert(buf->first->off == buf->first->buffer_len - 1);
871 evbuffer_drain(buf, buf->first->off - 1);
872 tt_assert(1 == evbuffer_get_length(buf));
873 tt_assert(buf->first->misalign > 0);
874 tt_assert(buf->first->off == 1);
875 buffer = buf->first->buffer;
876 tt_assert(evbuffer_expand(buf, 40) == 0);
877 tt_assert(buf->first == buf->last);
878 tt_assert(buf->first->off == 1);
879 tt_assert(buf->first->buffer == buffer);
880 tt_assert(buf->first->misalign == 0);
881 evbuffer_validate(buf);
884 /* add, expand, pull-up: This used to crash libevent. */
885 buf = evbuffer_new();
887 evbuffer_add(buf, data, sizeof(data));
888 evbuffer_add(buf, data, sizeof(data));
889 evbuffer_add(buf, data, sizeof(data));
891 evbuffer_validate(buf);
892 evbuffer_expand(buf, 1024);
893 evbuffer_validate(buf);
894 evbuffer_pullup(buf, -1);
895 evbuffer_validate(buf);
902 test_evbuffer_expand_overflow(void *ptr)
904 struct evbuffer *buf;
906 buf = evbuffer_new();
907 evbuffer_add(buf, "1", 1);
908 evbuffer_expand(buf, EVBUFFER_CHAIN_MAX);
909 evbuffer_validate(buf);
911 evbuffer_expand(buf, EV_SIZE_MAX);
912 evbuffer_validate(buf);
919 test_evbuffer_add1(void *ptr)
921 struct evbuffer *buf;
924 buf = evbuffer_new();
925 evbuffer_add(buf, "1", 1);
926 evbuffer_validate(buf);
927 evbuffer_expand(buf, 2048);
928 evbuffer_validate(buf);
929 evbuffer_add(buf, "2", 1);
930 evbuffer_validate(buf);
931 evbuffer_add_printf(buf, "3");
932 evbuffer_validate(buf);
934 tt_assert(evbuffer_get_length(buf) == 3);
935 str = (char *)evbuffer_pullup(buf, -1);
936 tt_assert(str[0] == '1');
937 tt_assert(str[1] == '2');
938 tt_assert(str[2] == '3');
944 test_evbuffer_add2(void *ptr)
946 struct evbuffer *buf;
947 static char data[4096];
948 int data_len = MIN_BUFFER_SIZE-EVBUFFER_CHAIN_SIZE-10;
952 memset(data, 'P', sizeof(data));
953 buf = evbuffer_new();
954 evbuffer_add(buf, data, data_len);
955 evbuffer_validate(buf);
956 evbuffer_expand(buf, 100);
957 evbuffer_validate(buf);
958 evbuffer_add(buf, "2", 1);
959 evbuffer_validate(buf);
960 evbuffer_add_printf(buf, "3");
961 evbuffer_validate(buf);
963 len = evbuffer_get_length(buf);
964 tt_assert(len == data_len+2);
965 str = (char *)evbuffer_pullup(buf, -1);
966 tt_assert(str[len-3] == 'P');
967 tt_assert(str[len-2] == '2');
968 tt_assert(str[len-1] == '3');
973 static int reference_cb_called;
975 reference_cb(const void *data, size_t len, void *extra)
977 tt_str_op(data, ==, "this is what we add as read-only memory.");
978 tt_int_op(len, ==, strlen(data));
979 tt_want(extra == (void *)0xdeadaffe);
980 ++reference_cb_called;
986 test_evbuffer_reference(void *ptr)
988 struct evbuffer *src = evbuffer_new();
989 struct evbuffer *dst = evbuffer_new();
990 struct evbuffer_iovec v[1];
991 const char *data = "this is what we add as read-only memory.";
992 reference_cb_called = 0;
994 tt_assert(evbuffer_add_reference(src, data, strlen(data),
995 reference_cb, (void *)0xdeadaffe) != -1);
997 evbuffer_reserve_space(dst, strlen(data), v, 1);
998 tt_assert(evbuffer_remove(src, v[0].iov_base, 10) != -1);
1000 evbuffer_validate(src);
1001 evbuffer_validate(dst);
1003 /* make sure that we don't write data at the beginning */
1004 evbuffer_prepend(src, "aaaaa", 5);
1005 evbuffer_validate(src);
1006 evbuffer_drain(src, 5);
1008 tt_assert(evbuffer_remove(src, ((char*)(v[0].iov_base)) + 10,
1009 strlen(data) - 10) != -1);
1011 v[0].iov_len = strlen(data);
1013 evbuffer_commit_space(dst, v, 1);
1014 evbuffer_validate(src);
1015 evbuffer_validate(dst);
1017 tt_int_op(reference_cb_called, ==, 1);
1019 tt_assert(!memcmp(evbuffer_pullup(dst, strlen(data)),
1020 data, strlen(data)));
1021 evbuffer_validate(dst);
1029 test_evbuffer_reference2(void *ptr)
1031 struct evbuffer *buf;
1032 static char data[4096];
1033 int data_len = MIN_BUFFER_SIZE-EVBUFFER_CHAIN_SIZE-10;
1037 memset(data, 'P', sizeof(data));
1038 buf = evbuffer_new();
1039 evbuffer_add(buf, data, data_len);
1040 evbuffer_validate(buf);
1041 evbuffer_expand(buf, 100);
1042 evbuffer_validate(buf);
1043 evbuffer_add_reference(buf, "2", 1, no_cleanup, NULL);
1044 evbuffer_validate(buf);
1045 evbuffer_add_printf(buf, "3");
1046 evbuffer_validate(buf);
1048 len = evbuffer_get_length(buf);
1049 tt_assert(len == data_len+2);
1050 str = (char *)evbuffer_pullup(buf, -1);
1051 tt_assert(str[len-3] == 'P');
1052 tt_assert(str[len-2] == '2');
1053 tt_assert(str[len-1] == '3');
1058 static struct event_base *addfile_test_event_base;
1059 static int addfile_test_done_writing;
1060 static int addfile_test_total_written;
1061 static int addfile_test_total_read;
1064 addfile_test_writecb(evutil_socket_t fd, short what, void *arg)
1066 struct evbuffer *b = arg;
1068 evbuffer_validate(b);
1069 while (evbuffer_get_length(b)) {
1070 r = evbuffer_write(b, fd);
1072 addfile_test_total_written += r;
1073 TT_BLATHER(("Wrote %d/%d bytes", r, addfile_test_total_written));
1075 int e = evutil_socket_geterror(fd);
1076 if (EVUTIL_ERR_RW_RETRIABLE(e))
1078 tt_fail_perror("write");
1079 event_base_loopexit(addfile_test_event_base,NULL);
1081 evbuffer_validate(b);
1083 addfile_test_done_writing = 1;
1086 event_base_loopexit(addfile_test_event_base,NULL);
1090 addfile_test_readcb(evutil_socket_t fd, short what, void *arg)
1092 struct evbuffer *b = arg;
1095 r = evbuffer_read(b, fd, 1024);
1097 addfile_test_total_read += r;
1098 TT_BLATHER(("Read %d/%d bytes", r, addfile_test_total_read));
1102 e = evutil_socket_geterror(fd);
1103 if (! EVUTIL_ERR_RW_RETRIABLE(e)) {
1104 tt_fail_perror("read");
1105 event_base_loopexit(addfile_test_event_base,NULL);
1108 if (addfile_test_done_writing &&
1109 addfile_test_total_read >= addfile_test_total_written) {
1110 event_base_loopexit(addfile_test_event_base,NULL);
1115 test_evbuffer_add_file(void *ptr)
1117 struct basic_test_data *testdata = ptr;
1118 const char *impl = testdata->setup_data;
1119 struct evbuffer *src = evbuffer_new(), *dest = evbuffer_new();
1120 char *tmpfilename = NULL;
1122 const char *expect_data;
1123 size_t datalen, expect_len;
1124 const char *compare;
1126 int want_ismapping = -1, want_cansendfile = -1;
1128 int use_segment = 1, use_bigfile = 0, map_from_offset = 0,
1129 view_from_offset = 0;
1130 struct evbuffer_file_segment *seg = NULL;
1131 ev_off_t starting_offset = 0, mapping_len = -1;
1132 ev_off_t segment_offset = 0, segment_len = -1;
1133 struct event *rev=NULL, *wev=NULL;
1134 struct event_base *base = testdata->base;
1135 evutil_socket_t pair[2] = {-1, -1};
1136 struct evutil_weakrand_state seed = { 123456789U };
1138 /* This test is highly parameterized based on substrings of its
1139 * argument. The strings are: */
1141 if (strstr(impl, "nosegment")) {
1142 /* If nosegment is set, use the older evbuffer_add_file
1146 if (strstr(impl, "bigfile")) {
1147 /* If bigfile is set, use a 512K file. Else use a smaller
1151 if (strstr(impl, "map_offset")) {
1152 /* If map_offset is set, we build the file segment starting
1153 * from a point other than byte 0 and ending somewhere other
1154 * than the last byte. Otherwise we map the whole thing */
1155 map_from_offset = 1;
1157 if (strstr(impl, "offset_in_segment")) {
1158 /* If offset_in_segment is set, we add a subsection of the
1159 * file semgment starting from a point other than byte 0 of
1161 view_from_offset = 1;
1163 if (strstr(impl, "sendfile")) {
1164 /* If sendfile is set, we try to use a sendfile/splice style
1166 flags = EVBUF_FS_DISABLE_MMAP;
1167 want_cansendfile = 1;
1169 } else if (strstr(impl, "mmap")) {
1170 /* If sendfile is set, we try to use a mmap/CreateFileMapping
1172 flags = EVBUF_FS_DISABLE_SENDFILE;
1174 want_cansendfile = 0;
1175 } else if (strstr(impl, "linear")) {
1176 /* If linear is set, we try to use a read-the-whole-thing
1178 flags = EVBUF_FS_DISABLE_SENDFILE|EVBUF_FS_DISABLE_MMAP;
1180 want_cansendfile = 0;
1181 } else if (strstr(impl, "default")) {
1182 /* The caller doesn't care which backend we use. */
1185 /* The caller must choose a backend. */
1186 TT_DIE(("Didn't recognize the implementation"));
1192 data = malloc(1024*512);
1194 for (i = 0; i < datalen; ++i)
1195 data[i] = (char)evutil_weakrand_(&seed);
1197 data = strdup("here is a relatively small string.");
1199 datalen = strlen(data);
1202 fd = regress_make_tmpfile(data, datalen, &tmpfilename);
1204 if (map_from_offset) {
1205 starting_offset = datalen/4 + 1;
1206 mapping_len = datalen / 2 - 1;
1207 expect_data = data + starting_offset;
1208 expect_len = mapping_len;
1211 expect_len = datalen;
1213 if (view_from_offset) {
1214 tt_assert(use_segment); /* Can't do this with add_file*/
1215 segment_offset = expect_len / 3;
1216 segment_len = expect_len / 2;
1217 expect_data = expect_data + segment_offset;
1218 expect_len = segment_len;
1222 seg = evbuffer_file_segment_new(fd, starting_offset,
1223 mapping_len, flags);
1225 if (want_ismapping >= 0) {
1226 if (seg->is_mapping != (unsigned)want_ismapping)
1229 if (want_cansendfile >= 0) {
1230 if (seg->can_sendfile != (unsigned)want_cansendfile)
1235 /* Say that it drains to a fd so that we can use sendfile. */
1236 evbuffer_set_flags(src, EVBUFFER_FLAG_DRAINS_TO_FD);
1238 #if defined(EVENT__HAVE_SENDFILE) && defined(__sun__) && defined(__svr4__)
1239 /* We need to use a pair of AF_INET sockets, since Solaris
1240 doesn't support sendfile() over AF_UNIX. */
1241 if (evutil_ersatz_socketpair_(AF_INET, SOCK_STREAM, 0, pair) == -1)
1242 tt_abort_msg("ersatz_socketpair failed");
1244 if (evutil_socketpair(AF_UNIX, SOCK_STREAM, 0, pair) == -1)
1245 tt_abort_msg("socketpair failed");
1247 evutil_make_socket_nonblocking(pair[0]);
1248 evutil_make_socket_nonblocking(pair[1]);
1250 tt_assert(fd != -1);
1253 tt_assert(evbuffer_add_file_segment(src, seg,
1254 segment_offset, segment_len)!=-1);
1256 tt_assert(evbuffer_add_file(src, fd, starting_offset,
1257 mapping_len) != -1);
1260 evbuffer_validate(src);
1262 addfile_test_event_base = base;
1263 addfile_test_done_writing = 0;
1264 addfile_test_total_written = 0;
1265 addfile_test_total_read = 0;
1267 wev = event_new(base, pair[0], EV_WRITE|EV_PERSIST,
1268 addfile_test_writecb, src);
1269 rev = event_new(base, pair[1], EV_READ|EV_PERSIST,
1270 addfile_test_readcb, dest);
1272 event_add(wev, NULL);
1273 event_add(rev, NULL);
1274 event_base_dispatch(base);
1276 evbuffer_validate(src);
1277 evbuffer_validate(dest);
1279 tt_assert(addfile_test_done_writing);
1280 tt_int_op(addfile_test_total_written, ==, expect_len);
1281 tt_int_op(addfile_test_total_read, ==, expect_len);
1283 compare = (char *)evbuffer_pullup(dest, expect_len);
1284 tt_assert(compare != NULL);
1285 if (memcmp(compare, expect_data, expect_len)) {
1286 tt_abort_msg("Data from add_file differs.");
1289 evbuffer_validate(dest);
1294 evbuffer_file_segment_free(seg);
1298 evbuffer_free(dest);
1300 evutil_closesocket(pair[0]);
1302 evutil_closesocket(pair[1]);
1308 unlink(tmpfilename);
1313 static int file_segment_cleanup_cb_called_count = 0;
1314 static struct evbuffer_file_segment const* file_segment_cleanup_cb_called_with = NULL;
1315 static int file_segment_cleanup_cb_called_with_flags = 0;
1316 static void* file_segment_cleanup_cb_called_with_arg = NULL;
1318 file_segment_cleanup_cp(struct evbuffer_file_segment const* seg, int flags, void* arg)
1320 ++file_segment_cleanup_cb_called_count;
1321 file_segment_cleanup_cb_called_with = seg;
1322 file_segment_cleanup_cb_called_with_flags = flags;
1323 file_segment_cleanup_cb_called_with_arg = arg;
1327 test_evbuffer_file_segment_add_cleanup_cb(void* ptr)
1329 char *tmpfilename = NULL;
1331 struct evbuffer *evb = NULL;
1332 struct evbuffer_file_segment *seg = NULL, *segptr;
1333 char const* arg = "token";
1335 fd = regress_make_tmpfile("file_segment_test_file", 22, &tmpfilename);
1336 tt_int_op(fd, >=, 0);
1338 evb = evbuffer_new();
1341 segptr = seg = evbuffer_file_segment_new(fd, 0, -1, 0);
1344 evbuffer_file_segment_add_cleanup_cb(
1345 seg, &file_segment_cleanup_cp, (void*)arg);
1347 tt_assert(fd != -1);
1349 tt_assert(evbuffer_add_file_segment(evb, seg, 0, -1)!=-1);
1351 evbuffer_validate(evb);
1353 tt_int_op(file_segment_cleanup_cb_called_count, ==, 0);
1354 evbuffer_file_segment_free(seg);
1355 seg = NULL; /* Prevent double-free. */
1357 tt_int_op(file_segment_cleanup_cb_called_count, ==, 0);
1359 evb = NULL; /* pevent double-free */
1361 tt_int_op(file_segment_cleanup_cb_called_count, ==, 1);
1362 tt_assert(file_segment_cleanup_cb_called_with == segptr);
1363 tt_assert(file_segment_cleanup_cb_called_with_flags == 0);
1364 tt_assert(file_segment_cleanup_cb_called_with_arg == (void*)arg);
1370 evbuffer_file_segment_free(seg);
1372 unlink(tmpfilename);
1377 #ifndef EVENT__DISABLE_MM_REPLACEMENT
1379 failing_malloc(size_t how_much)
1387 test_evbuffer_readln(void *ptr)
1389 struct evbuffer *evb = evbuffer_new();
1390 struct evbuffer *evb_tmp = evbuffer_new();
1395 #define tt_line_eq(content) \
1397 if (!cp || sz != strlen(content) || strcmp(cp, content)) { \
1398 TT_DIE(("Wanted %s; got %s [%d]", content, cp, (int)sz)); \
1403 s = "complex silly newline\r\n\n\r\n\n\rmore\0\n";
1404 evbuffer_add(evb, s, strlen(s)+2);
1405 evbuffer_validate(evb);
1406 cp = evbuffer_readln(evb, &sz, EVBUFFER_EOL_ANY);
1407 tt_line_eq("complex silly newline");
1409 evbuffer_validate(evb);
1410 cp = evbuffer_readln(evb, &sz, EVBUFFER_EOL_ANY);
1411 if (!cp || sz != 5 || memcmp(cp, "more\0\0", 6))
1412 tt_abort_msg("Not as expected");
1413 tt_uint_op(evbuffer_get_length(evb), ==, 0);
1414 evbuffer_validate(evb);
1416 evbuffer_add(evb, s, strlen(s));
1418 evbuffer_validate(evb);
1419 cp = evbuffer_readln(evb, &sz, EVBUFFER_EOL_ANY);
1422 evbuffer_validate(evb);
1423 cp = evbuffer_readln(evb, &sz, EVBUFFER_EOL_ANY);
1425 evbuffer_validate(evb);
1426 evbuffer_drain(evb, evbuffer_get_length(evb));
1427 tt_assert(evbuffer_get_length(evb) == 0);
1428 evbuffer_validate(evb);
1431 s = "Line with\rin the middle\nLine with good crlf\r\n\nfinal\n";
1432 evbuffer_add(evb, s, strlen(s));
1433 evbuffer_validate(evb);
1434 cp = evbuffer_readln(evb, &sz, EVBUFFER_EOL_CRLF);
1435 tt_line_eq("Line with\rin the middle");
1437 evbuffer_validate(evb);
1439 cp = evbuffer_readln(evb, &sz, EVBUFFER_EOL_CRLF);
1440 tt_line_eq("Line with good crlf");
1442 evbuffer_validate(evb);
1444 cp = evbuffer_readln(evb, &sz, EVBUFFER_EOL_CRLF);
1447 evbuffer_validate(evb);
1449 cp = evbuffer_readln(evb, &sz, EVBUFFER_EOL_CRLF);
1450 tt_line_eq("final");
1452 evbuffer_validate(evb);
1453 evbuffer_add(evb, s, 1);
1454 evbuffer_validate(evb);
1456 cp = evbuffer_readln(evb, &sz, EVBUFFER_EOL_CRLF);
1458 evbuffer_validate(evb);
1460 /* Test CRLF_STRICT */
1461 s = " and a bad crlf\nand a good one\r\n\r\nMore\r";
1462 evbuffer_add(evb, s, strlen(s));
1463 evbuffer_validate(evb);
1464 cp = evbuffer_readln(evb, &sz, EVBUFFER_EOL_CRLF_STRICT);
1465 tt_line_eq("x and a bad crlf\nand a good one");
1467 evbuffer_validate(evb);
1469 cp = evbuffer_readln(evb, &sz, EVBUFFER_EOL_CRLF_STRICT);
1472 evbuffer_validate(evb);
1474 cp = evbuffer_readln(evb, &sz, EVBUFFER_EOL_CRLF_STRICT);
1476 evbuffer_validate(evb);
1477 evbuffer_add(evb, "\n", 1);
1478 evbuffer_validate(evb);
1480 cp = evbuffer_readln(evb, &sz, EVBUFFER_EOL_CRLF_STRICT);
1483 tt_assert(evbuffer_get_length(evb) == 0);
1484 evbuffer_validate(evb);
1486 s = "An internal CR\r is not an eol\r\nNor is a lack of one";
1487 evbuffer_add(evb, s, strlen(s));
1488 cp = evbuffer_readln(evb, &sz, EVBUFFER_EOL_CRLF_STRICT);
1489 tt_line_eq("An internal CR\r is not an eol");
1491 evbuffer_validate(evb);
1493 cp = evbuffer_readln(evb, &sz, EVBUFFER_EOL_CRLF_STRICT);
1495 evbuffer_validate(evb);
1497 evbuffer_add(evb, "\r\n", 2);
1498 evbuffer_validate(evb);
1499 cp = evbuffer_readln(evb, &sz, EVBUFFER_EOL_CRLF_STRICT);
1500 tt_line_eq("Nor is a lack of one");
1502 tt_assert(evbuffer_get_length(evb) == 0);
1503 evbuffer_validate(evb);
1506 s = "An\rand a nl\n\nText";
1507 evbuffer_add(evb, s, strlen(s));
1508 evbuffer_validate(evb);
1510 cp = evbuffer_readln(evb, &sz, EVBUFFER_EOL_LF);
1511 tt_line_eq("An\rand a nl");
1513 evbuffer_validate(evb);
1515 cp = evbuffer_readln(evb, &sz, EVBUFFER_EOL_LF);
1518 evbuffer_validate(evb);
1520 cp = evbuffer_readln(evb, &sz, EVBUFFER_EOL_LF);
1523 evbuffer_add(evb, "\n", 1);
1524 evbuffer_validate(evb);
1525 cp = evbuffer_readln(evb, &sz, EVBUFFER_EOL_LF);
1528 evbuffer_validate(evb);
1531 tt_int_op(evbuffer_get_length(evb), ==, 0);
1535 "The all-zeros character which may serve\0"
1536 "to accomplish time fill\0and media fill";
1537 /* Add all but the final NUL of x. */
1538 evbuffer_add(evb, x, sizeof(x)-1);
1540 cp = evbuffer_readln(evb, &sz, EVBUFFER_EOL_NUL);
1541 tt_line_eq("NUL\n");
1543 cp = evbuffer_readln(evb, &sz, EVBUFFER_EOL_NUL);
1546 cp = evbuffer_readln(evb, &sz, EVBUFFER_EOL_NUL);
1547 tt_line_eq("The all-zeros character which may serve");
1549 cp = evbuffer_readln(evb, &sz, EVBUFFER_EOL_NUL);
1550 tt_line_eq("to accomplish time fill");
1552 cp = evbuffer_readln(evb, &sz, EVBUFFER_EOL_NUL);
1553 tt_ptr_op(cp, ==, NULL);
1554 evbuffer_drain(evb, -1);
1556 /* Test CRLF_STRICT - across boundaries*/
1557 s = " and a bad crlf\nand a good one\r";
1558 evbuffer_add(evb_tmp, s, strlen(s));
1559 evbuffer_validate(evb);
1560 evbuffer_add_buffer(evb, evb_tmp);
1561 evbuffer_validate(evb);
1563 evbuffer_add(evb_tmp, s, strlen(s));
1564 evbuffer_validate(evb);
1565 evbuffer_add_buffer(evb, evb_tmp);
1566 evbuffer_validate(evb);
1568 evbuffer_add(evb_tmp, s, strlen(s));
1569 evbuffer_validate(evb);
1570 evbuffer_add_buffer(evb, evb_tmp);
1571 evbuffer_validate(evb);
1573 cp = evbuffer_readln(evb, &sz, EVBUFFER_EOL_CRLF_STRICT);
1574 tt_line_eq(" and a bad crlf\nand a good one");
1576 evbuffer_validate(evb);
1578 cp = evbuffer_readln(evb, &sz, EVBUFFER_EOL_CRLF_STRICT);
1581 evbuffer_validate(evb);
1583 cp = evbuffer_readln(evb, &sz, EVBUFFER_EOL_CRLF_STRICT);
1586 evbuffer_validate(evb);
1587 evbuffer_add(evb, "\n", 1);
1588 evbuffer_validate(evb);
1589 cp = evbuffer_readln(evb, &sz, EVBUFFER_EOL_CRLF_STRICT);
1591 free(cp); cp = NULL;
1592 evbuffer_validate(evb);
1593 tt_assert(evbuffer_get_length(evb) == 0);
1595 /* Test memory problem*/
1596 s = "one line\ntwo line\nblue line";
1597 evbuffer_add(evb_tmp, s, strlen(s));
1598 evbuffer_validate(evb);
1599 evbuffer_add_buffer(evb, evb_tmp);
1600 evbuffer_validate(evb);
1602 cp = evbuffer_readln(evb, &sz, EVBUFFER_EOL_LF);
1603 tt_line_eq("one line");
1604 free(cp); cp = NULL;
1605 evbuffer_validate(evb);
1607 /* the next call to readline should fail */
1608 #ifndef EVENT__DISABLE_MM_REPLACEMENT
1609 event_set_mem_functions(failing_malloc, realloc, free);
1610 cp = evbuffer_readln(evb, &sz, EVBUFFER_EOL_LF);
1611 tt_assert(cp == NULL);
1612 evbuffer_validate(evb);
1614 /* now we should get the next line back */
1615 event_set_mem_functions(malloc, realloc, free);
1617 cp = evbuffer_readln(evb, &sz, EVBUFFER_EOL_LF);
1618 tt_line_eq("two line");
1619 free(cp); cp = NULL;
1620 evbuffer_validate(evb);
1624 evbuffer_free(evb_tmp);
1629 test_evbuffer_search_eol(void *ptr)
1631 struct evbuffer *buf = evbuffer_new();
1632 struct evbuffer_ptr ptr1, ptr2;
1636 s = "string! \r\n\r\nx\n";
1637 evbuffer_add(buf, s, strlen(s));
1639 ptr1 = evbuffer_search_eol(buf, NULL, &eol_len, EVBUFFER_EOL_CRLF);
1640 tt_int_op(ptr1.pos, ==, 8);
1641 tt_int_op(eol_len, ==, 2);
1644 ptr2 = evbuffer_search_eol(buf, &ptr1, &eol_len, EVBUFFER_EOL_CRLF);
1645 tt_int_op(ptr2.pos, ==, 8);
1646 tt_int_op(eol_len, ==, 2);
1648 evbuffer_ptr_set(buf, &ptr1, 1, EVBUFFER_PTR_ADD);
1650 ptr2 = evbuffer_search_eol(buf, &ptr1, &eol_len, EVBUFFER_EOL_CRLF);
1651 tt_int_op(ptr2.pos, ==, 9);
1652 tt_int_op(eol_len, ==, 1);
1655 ptr2 = evbuffer_search_eol(buf, &ptr1, &eol_len, EVBUFFER_EOL_CRLF_STRICT);
1656 tt_int_op(ptr2.pos, ==, 10);
1657 tt_int_op(eol_len, ==, 2);
1660 ptr1 = evbuffer_search_eol(buf, NULL, &eol_len, EVBUFFER_EOL_LF);
1661 tt_int_op(ptr1.pos, ==, 9);
1662 tt_int_op(eol_len, ==, 1);
1665 ptr2 = evbuffer_search_eol(buf, &ptr1, &eol_len, EVBUFFER_EOL_LF);
1666 tt_int_op(ptr2.pos, ==, 9);
1667 tt_int_op(eol_len, ==, 1);
1669 evbuffer_ptr_set(buf, &ptr1, 1, EVBUFFER_PTR_ADD);
1671 ptr2 = evbuffer_search_eol(buf, &ptr1, &eol_len, EVBUFFER_EOL_LF);
1672 tt_int_op(ptr2.pos, ==, 11);
1673 tt_int_op(eol_len, ==, 1);
1675 tt_assert(evbuffer_ptr_set(buf, &ptr1, evbuffer_get_length(buf), EVBUFFER_PTR_SET) == 0);
1677 ptr2 = evbuffer_search_eol(buf, &ptr1, &eol_len, EVBUFFER_EOL_LF);
1678 tt_int_op(ptr2.pos, ==, -1);
1679 tt_int_op(eol_len, ==, 0);
1686 test_evbuffer_iterative(void *ptr)
1688 struct evbuffer *buf = evbuffer_new();
1689 const char *abc = "abcdefghijklmnopqrstvuwxyzabcdefghijklmnopqrstvuwxyzabcdefghijklmnopqrstvuwxyzabcdefghijklmnopqrstvuwxyz";
1690 unsigned i, j, sum, n;
1694 for (i = 0; i < 1000; ++i) {
1695 for (j = 1; j < strlen(abc); ++j) {
1697 evutil_snprintf(format, sizeof(format), "%%%u.%us", j, j);
1698 evbuffer_add_printf(buf, format, abc);
1700 /* Only check for rep violations every so often.
1701 Walking over the whole list of chains can get
1702 pretty expensive as it gets long.
1705 evbuffer_validate(buf);
1711 evbuffer_validate(buf);
1713 tt_uint_op(sum, ==, evbuffer_get_length(buf));
1718 evbuffer_get_waste(buf, &a, &w, &u);
1720 printf("Allocated: %u.\nWasted: %u.\nUsed: %u.",
1721 (unsigned)a, (unsigned)w, (unsigned)u);
1722 tt_assert( ((double)w)/a < .125);
1730 test_evbuffer_find(void *ptr)
1733 const char* test1 = "1234567890\r\n";
1734 const char* test2 = "1234567890\r";
1735 #define EVBUFFER_INITIAL_LENGTH 256
1736 char test3[EVBUFFER_INITIAL_LENGTH];
1738 struct evbuffer * buf = evbuffer_new();
1742 /* make sure evbuffer_find doesn't match past the end of the buffer */
1743 evbuffer_add(buf, (unsigned char*)test1, strlen(test1));
1744 evbuffer_validate(buf);
1745 evbuffer_drain(buf, strlen(test1));
1746 evbuffer_validate(buf);
1747 evbuffer_add(buf, (unsigned char*)test2, strlen(test2));
1748 evbuffer_validate(buf);
1749 p = evbuffer_find(buf, (unsigned char*)"\r\n", 2);
1753 * drain the buffer and do another find; in r309 this would
1754 * read past the allocated buffer causing a valgrind error.
1756 evbuffer_drain(buf, strlen(test2));
1757 evbuffer_validate(buf);
1758 for (i = 0; i < EVBUFFER_INITIAL_LENGTH; ++i)
1760 test3[EVBUFFER_INITIAL_LENGTH - 1] = 'x';
1761 evbuffer_add(buf, (unsigned char *)test3, EVBUFFER_INITIAL_LENGTH);
1762 evbuffer_validate(buf);
1763 p = evbuffer_find(buf, (unsigned char *)"xy", 2);
1766 /* simple test for match at end of allocated buffer */
1767 p = evbuffer_find(buf, (unsigned char *)"ax", 2);
1768 tt_assert(p != NULL);
1769 tt_want(strncmp((char*)p, "ax", 2) == 0);
1777 test_evbuffer_ptr_set(void *ptr)
1779 struct evbuffer *buf = evbuffer_new();
1780 struct evbuffer_ptr pos;
1781 struct evbuffer_iovec v[1];
1785 tt_int_op(evbuffer_get_length(buf), ==, 0);
1787 tt_assert(evbuffer_ptr_set(buf, &pos, 0, EVBUFFER_PTR_SET) == 0);
1788 tt_assert(pos.pos == 0);
1789 tt_assert(evbuffer_ptr_set(buf, &pos, 1, EVBUFFER_PTR_ADD) == -1);
1790 tt_assert(pos.pos == -1);
1791 tt_assert(evbuffer_ptr_set(buf, &pos, 1, EVBUFFER_PTR_SET) == -1);
1792 tt_assert(pos.pos == -1);
1794 /* create some chains */
1795 evbuffer_reserve_space(buf, 5000, v, 1);
1796 v[0].iov_len = 5000;
1797 memset(v[0].iov_base, 1, v[0].iov_len);
1798 evbuffer_commit_space(buf, v, 1);
1799 evbuffer_validate(buf);
1801 evbuffer_reserve_space(buf, 4000, v, 1);
1802 v[0].iov_len = 4000;
1803 memset(v[0].iov_base, 2, v[0].iov_len);
1804 evbuffer_commit_space(buf, v, 1);
1806 evbuffer_reserve_space(buf, 3000, v, 1);
1807 v[0].iov_len = 3000;
1808 memset(v[0].iov_base, 3, v[0].iov_len);
1809 evbuffer_commit_space(buf, v, 1);
1810 evbuffer_validate(buf);
1812 tt_int_op(evbuffer_get_length(buf), ==, 12000);
1814 tt_assert(evbuffer_ptr_set(buf, &pos, 13000, EVBUFFER_PTR_SET) == -1);
1815 tt_assert(pos.pos == -1);
1816 tt_assert(evbuffer_ptr_set(buf, &pos, 0, EVBUFFER_PTR_SET) == 0);
1817 tt_assert(pos.pos == 0);
1818 tt_assert(evbuffer_ptr_set(buf, &pos, 13000, EVBUFFER_PTR_ADD) == -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, 10000, EVBUFFER_PTR_ADD) == 0);
1823 tt_assert(pos.pos == 10000);
1824 tt_assert(evbuffer_ptr_set(buf, &pos, 1000, EVBUFFER_PTR_ADD) == 0);
1825 tt_assert(pos.pos == 11000);
1826 tt_assert(evbuffer_ptr_set(buf, &pos, 1000, EVBUFFER_PTR_ADD) == 0);
1827 tt_assert(pos.pos == 12000);
1828 tt_assert(evbuffer_ptr_set(buf, &pos, 1000, EVBUFFER_PTR_ADD) == -1);
1829 tt_assert(pos.pos == -1);
1837 test_evbuffer_search(void *ptr)
1839 struct evbuffer *buf = evbuffer_new();
1840 struct evbuffer *tmp = evbuffer_new();
1841 struct evbuffer_ptr pos, end;
1846 pos = evbuffer_search(buf, "x", 1, NULL);
1847 tt_int_op(pos.pos, ==, -1);
1848 tt_assert(evbuffer_ptr_set(buf, &pos, 0, EVBUFFER_PTR_SET) == 0);
1849 pos = evbuffer_search(buf, "x", 1, &pos);
1850 tt_int_op(pos.pos, ==, -1);
1851 tt_assert(evbuffer_ptr_set(buf, &pos, 0, EVBUFFER_PTR_SET) == 0);
1852 pos = evbuffer_search_range(buf, "x", 1, &pos, &pos);
1853 tt_int_op(pos.pos, ==, -1);
1854 tt_assert(evbuffer_ptr_set(buf, &pos, 0, EVBUFFER_PTR_SET) == 0);
1855 pos = evbuffer_search_range(buf, "x", 1, &pos, NULL);
1856 tt_int_op(pos.pos, ==, -1);
1858 /* set up our chains */
1859 evbuffer_add_printf(tmp, "hello"); /* 5 chars */
1860 evbuffer_add_buffer(buf, tmp);
1861 evbuffer_add_printf(tmp, "foo"); /* 3 chars */
1862 evbuffer_add_buffer(buf, tmp);
1863 evbuffer_add_printf(tmp, "cat"); /* 3 chars */
1864 evbuffer_add_buffer(buf, tmp);
1865 evbuffer_add_printf(tmp, "attack");
1866 evbuffer_add_buffer(buf, tmp);
1868 pos = evbuffer_search(buf, "attack", 6, NULL);
1869 tt_int_op(pos.pos, ==, 11);
1870 pos = evbuffer_search(buf, "attacker", 8, NULL);
1871 tt_int_op(pos.pos, ==, -1);
1873 /* test continuing search */
1874 pos = evbuffer_search(buf, "oc", 2, NULL);
1875 tt_int_op(pos.pos, ==, 7);
1876 pos = evbuffer_search(buf, "cat", 3, &pos);
1877 tt_int_op(pos.pos, ==, 8);
1878 pos = evbuffer_search(buf, "tacking", 7, &pos);
1879 tt_int_op(pos.pos, ==, -1);
1881 evbuffer_ptr_set(buf, &pos, 5, EVBUFFER_PTR_SET);
1882 pos = evbuffer_search(buf, "foo", 3, &pos);
1883 tt_int_op(pos.pos, ==, 5);
1885 evbuffer_ptr_set(buf, &pos, 2, EVBUFFER_PTR_ADD);
1886 pos = evbuffer_search(buf, "tat", 3, &pos);
1887 tt_int_op(pos.pos, ==, 10);
1889 /* test bounded search. */
1890 /* Set "end" to the first t in "attack". */
1891 evbuffer_ptr_set(buf, &end, 12, EVBUFFER_PTR_SET);
1892 pos = evbuffer_search_range(buf, "foo", 3, NULL, &end);
1893 tt_int_op(pos.pos, ==, 5);
1894 pos = evbuffer_search_range(buf, "foocata", 7, NULL, &end);
1895 tt_int_op(pos.pos, ==, 5);
1896 pos = evbuffer_search_range(buf, "foocatat", 8, NULL, &end);
1897 tt_int_op(pos.pos, ==, -1);
1898 pos = evbuffer_search_range(buf, "ack", 3, NULL, &end);
1899 tt_int_op(pos.pos, ==, -1);
1901 /* Set "end" after the last byte in the buffer. */
1902 tt_assert(evbuffer_ptr_set(buf, &end, 17, EVBUFFER_PTR_SET) == 0);
1904 pos = evbuffer_search_range(buf, "attack", 6, NULL, &end);
1905 tt_int_op(pos.pos, ==, 11);
1906 tt_assert(evbuffer_ptr_set(buf, &pos, 11, EVBUFFER_PTR_SET) == 0);
1907 pos = evbuffer_search_range(buf, "attack", 6, &pos, &end);
1908 tt_int_op(pos.pos, ==, 11);
1909 tt_assert(evbuffer_ptr_set(buf, &pos, 17, EVBUFFER_PTR_SET) == 0);
1910 pos = evbuffer_search_range(buf, "attack", 6, &pos, &end);
1911 tt_int_op(pos.pos, ==, -1);
1912 tt_assert(evbuffer_ptr_set(buf, &pos, 17, EVBUFFER_PTR_SET) == 0);
1913 pos = evbuffer_search_range(buf, "attack", 6, &pos, NULL);
1914 tt_int_op(pos.pos, ==, -1);
1924 log_change_callback(struct evbuffer *buffer,
1925 const struct evbuffer_cb_info *cbinfo,
1929 size_t old_len = cbinfo->orig_size;
1930 size_t new_len = old_len + cbinfo->n_added - cbinfo->n_deleted;
1931 struct evbuffer *out = arg;
1932 evbuffer_add_printf(out, "%lu->%lu; ", (unsigned long)old_len,
1933 (unsigned long)new_len);
1936 self_draining_callback(struct evbuffer *evbuffer, size_t old_len,
1937 size_t new_len, void *arg)
1939 if (new_len > old_len)
1940 evbuffer_drain(evbuffer, new_len);
1944 test_evbuffer_callbacks(void *ptr)
1946 struct evbuffer *buf = evbuffer_new();
1947 struct evbuffer *buf_out1 = evbuffer_new();
1948 struct evbuffer *buf_out2 = evbuffer_new();
1949 struct evbuffer_cb_entry *cb1, *cb2;
1952 tt_assert(buf_out1);
1953 tt_assert(buf_out2);
1955 cb1 = evbuffer_add_cb(buf, log_change_callback, buf_out1);
1956 cb2 = evbuffer_add_cb(buf, log_change_callback, buf_out2);
1958 /* Let's run through adding and deleting some stuff from the buffer
1959 * and turning the callbacks on and off and removing them. The callback
1960 * adds a summary of length changes to buf_out1/buf_out2 when called. */
1962 evbuffer_add_printf(buf, "The %d magic words are spotty pudding", 2);
1963 evbuffer_validate(buf);
1964 evbuffer_cb_clear_flags(buf, cb2, EVBUFFER_CB_ENABLED);
1965 evbuffer_drain(buf, 10); /*36->26*/
1966 evbuffer_validate(buf);
1967 evbuffer_prepend(buf, "Hello", 5);/*26->31*/
1968 evbuffer_cb_set_flags(buf, cb2, EVBUFFER_CB_ENABLED);
1969 evbuffer_add_reference(buf, "Goodbye", 7, NULL, NULL); /*31->38*/
1970 evbuffer_remove_cb_entry(buf, cb1);
1971 evbuffer_validate(buf);
1972 evbuffer_drain(buf, evbuffer_get_length(buf)); /*38->0*/;
1973 tt_assert(-1 == evbuffer_remove_cb(buf, log_change_callback, NULL));
1974 evbuffer_add(buf, "X", 1); /* 0->1 */
1975 tt_assert(!evbuffer_remove_cb(buf, log_change_callback, buf_out2));
1976 evbuffer_validate(buf);
1978 tt_str_op((const char *) evbuffer_pullup(buf_out1, -1), ==,
1979 "0->36; 36->26; 26->31; 31->38; ");
1980 tt_str_op((const char *) evbuffer_pullup(buf_out2, -1), ==,
1981 "0->36; 31->38; 38->0; 0->1; ");
1982 evbuffer_drain(buf_out1, evbuffer_get_length(buf_out1));
1983 evbuffer_drain(buf_out2, evbuffer_get_length(buf_out2));
1984 /* Let's test the obsolete buffer_setcb function too. */
1985 cb1 = evbuffer_add_cb(buf, log_change_callback, buf_out1);
1986 tt_assert(cb1 != NULL);
1987 cb2 = evbuffer_add_cb(buf, log_change_callback, buf_out2);
1988 tt_assert(cb2 != NULL);
1989 tt_int_op(evbuffer_setcb(buf, self_draining_callback, NULL), ==, 0);
1990 evbuffer_add_printf(buf, "This should get drained right away.");
1991 tt_uint_op(evbuffer_get_length(buf), ==, 0);
1992 tt_uint_op(evbuffer_get_length(buf_out1), ==, 0);
1993 tt_uint_op(evbuffer_get_length(buf_out2), ==, 0);
1994 tt_int_op(evbuffer_setcb(buf, NULL, NULL), ==, 0);
1995 evbuffer_add_printf(buf, "This will not.");
1996 tt_str_op((const char *) evbuffer_pullup(buf, -1), ==, "This will not.");
1997 evbuffer_validate(buf);
1998 evbuffer_drain(buf, evbuffer_get_length(buf));
1999 evbuffer_validate(buf);
2001 /* Now let's try a suspended callback. */
2002 cb1 = evbuffer_add_cb(buf, log_change_callback, buf_out1);
2003 cb2 = evbuffer_add_cb(buf, log_change_callback, buf_out2);
2004 evbuffer_cb_suspend(buf,cb2);
2005 evbuffer_prepend(buf,"Hello world",11); /*0->11*/
2006 evbuffer_validate(buf);
2007 evbuffer_cb_suspend(buf,cb1);
2008 evbuffer_add(buf,"more",4); /* 11->15 */
2009 evbuffer_cb_unsuspend(buf,cb2);
2010 evbuffer_drain(buf, 4); /* 15->11 */
2011 evbuffer_cb_unsuspend(buf,cb1);
2012 evbuffer_drain(buf, evbuffer_get_length(buf)); /* 11->0 */
2014 tt_str_op(evbuffer_pullup(buf_out1, -1), ==,
2015 "0->11; 11->11; 11->0; ");
2016 tt_str_op(evbuffer_pullup(buf_out2, -1), ==,
2017 "0->15; 15->11; 11->0; ");
2020 /* the next call to readline should fail */
2021 #ifndef EVENT__DISABLE_MM_REPLACEMENT
2022 event_set_mem_functions(failing_malloc, realloc, free);
2023 tt_int_op(evbuffer_setcb(buf, self_draining_callback, NULL), ==, -1);
2024 evbuffer_validate(buf);
2025 event_set_mem_functions(malloc, realloc, free);
2032 evbuffer_free(buf_out1);
2034 evbuffer_free(buf_out2);
2037 static int ref_done_cb_called_count = 0;
2038 static void *ref_done_cb_called_with = NULL;
2039 static const void *ref_done_cb_called_with_data = NULL;
2040 static size_t ref_done_cb_called_with_len = 0;
2041 static void ref_done_cb(const void *data, size_t len, void *info)
2043 ++ref_done_cb_called_count;
2044 ref_done_cb_called_with = info;
2045 ref_done_cb_called_with_data = data;
2046 ref_done_cb_called_with_len = len;
2050 test_evbuffer_add_reference(void *ptr)
2052 const char chunk1[] = "If you have found the answer to such a problem";
2053 const char chunk2[] = "you ought to write it up for publication";
2054 /* -- Knuth's "Notes on the Exercises" from TAOCP */
2056 size_t len1 = strlen(chunk1), len2=strlen(chunk2);
2058 struct evbuffer *buf1 = NULL, *buf2 = NULL;
2060 buf1 = evbuffer_new();
2063 evbuffer_add_reference(buf1, chunk1, len1, ref_done_cb, (void*)111);
2064 evbuffer_add(buf1, ", ", 2);
2065 evbuffer_add_reference(buf1, chunk2, len2, ref_done_cb, (void*)222);
2066 tt_int_op(evbuffer_get_length(buf1), ==, len1+len2+2);
2068 /* Make sure we can drain a little from a reference. */
2069 tt_int_op(evbuffer_remove(buf1, tmp, 6), ==, 6);
2070 tt_int_op(memcmp(tmp, "If you", 6), ==, 0);
2071 tt_int_op(evbuffer_remove(buf1, tmp, 5), ==, 5);
2072 tt_int_op(memcmp(tmp, " have", 5), ==, 0);
2074 /* Make sure that prepending does not meddle with immutable data */
2075 tt_int_op(evbuffer_prepend(buf1, "I have ", 7), ==, 0);
2076 tt_int_op(memcmp(chunk1, "If you", 6), ==, 0);
2077 evbuffer_validate(buf1);
2079 /* Make sure that when the chunk is over, the callback is invoked. */
2080 evbuffer_drain(buf1, 7); /* Remove prepended stuff. */
2081 evbuffer_drain(buf1, len1-11-1); /* remove all but one byte of chunk1 */
2082 tt_int_op(ref_done_cb_called_count, ==, 0);
2083 evbuffer_remove(buf1, tmp, 1);
2084 tt_int_op(tmp[0], ==, 'm');
2085 tt_assert(ref_done_cb_called_with == (void*)111);
2086 tt_assert(ref_done_cb_called_with_data == chunk1);
2087 tt_assert(ref_done_cb_called_with_len == len1);
2088 tt_int_op(ref_done_cb_called_count, ==, 1);
2089 evbuffer_validate(buf1);
2091 /* Drain some of the remaining chunk, then add it to another buffer */
2092 evbuffer_drain(buf1, 6); /* Remove the ", you ". */
2093 buf2 = evbuffer_new();
2095 tt_int_op(ref_done_cb_called_count, ==, 1);
2096 evbuffer_add(buf2, "I ", 2);
2098 evbuffer_add_buffer(buf2, buf1);
2099 tt_int_op(ref_done_cb_called_count, ==, 1);
2100 evbuffer_remove(buf2, tmp, 16);
2101 tt_int_op(memcmp("I ought to write", tmp, 16), ==, 0);
2102 evbuffer_drain(buf2, evbuffer_get_length(buf2));
2103 tt_int_op(ref_done_cb_called_count, ==, 2);
2104 tt_assert(ref_done_cb_called_with == (void*)222);
2105 evbuffer_validate(buf2);
2107 /* Now add more stuff to buf1 and make sure that it gets removed on
2109 evbuffer_add(buf1, "You shake and shake the ", 24);
2110 evbuffer_add_reference(buf1, "ketchup bottle", 14, ref_done_cb,
2112 evbuffer_add(buf1, ". Nothing comes and then a lot'll.", 35);
2113 evbuffer_free(buf1);
2115 tt_int_op(ref_done_cb_called_count, ==, 3);
2116 tt_assert(ref_done_cb_called_with == (void*)3333);
2120 evbuffer_free(buf1);
2122 evbuffer_free(buf2);
2126 test_evbuffer_multicast(void *ptr)
2128 const char chunk1[] = "If you have found the answer to such a problem";
2129 const char chunk2[] = "you ought to write it up for publication";
2130 /* -- Knuth's "Notes on the Exercises" from TAOCP */
2132 size_t len1 = strlen(chunk1), len2=strlen(chunk2);
2134 struct evbuffer *buf1 = NULL, *buf2 = NULL;
2136 buf1 = evbuffer_new();
2139 evbuffer_add(buf1, chunk1, len1);
2140 evbuffer_add(buf1, ", ", 2);
2141 evbuffer_add(buf1, chunk2, len2);
2142 tt_int_op(evbuffer_get_length(buf1), ==, len1+len2+2);
2144 buf2 = evbuffer_new();
2147 tt_int_op(evbuffer_add_buffer_reference(buf2, buf1), ==, 0);
2148 /* nested references are not allowed */
2149 tt_int_op(evbuffer_add_buffer_reference(buf2, buf2), ==, -1);
2150 tt_int_op(evbuffer_add_buffer_reference(buf1, buf2), ==, -1);
2152 /* both buffers contain the same amount of data */
2153 tt_int_op(evbuffer_get_length(buf1), ==, evbuffer_get_length(buf1));
2155 /* Make sure we can drain a little from the first buffer. */
2156 tt_int_op(evbuffer_remove(buf1, tmp, 6), ==, 6);
2157 tt_int_op(memcmp(tmp, "If you", 6), ==, 0);
2158 tt_int_op(evbuffer_remove(buf1, tmp, 5), ==, 5);
2159 tt_int_op(memcmp(tmp, " have", 5), ==, 0);
2161 /* Make sure that prepending does not meddle with immutable data */
2162 tt_int_op(evbuffer_prepend(buf1, "I have ", 7), ==, 0);
2163 tt_int_op(memcmp(chunk1, "If you", 6), ==, 0);
2164 evbuffer_validate(buf1);
2166 /* Make sure we can drain a little from the second buffer. */
2167 tt_int_op(evbuffer_remove(buf2, tmp, 6), ==, 6);
2168 tt_int_op(memcmp(tmp, "If you", 6), ==, 0);
2169 tt_int_op(evbuffer_remove(buf2, tmp, 5), ==, 5);
2170 tt_int_op(memcmp(tmp, " have", 5), ==, 0);
2172 /* Make sure that prepending does not meddle with immutable data */
2173 tt_int_op(evbuffer_prepend(buf2, "I have ", 7), ==, 0);
2174 tt_int_op(memcmp(chunk1, "If you", 6), ==, 0);
2175 evbuffer_validate(buf2);
2177 /* Make sure the data can be read from the second buffer when the first is freed */
2178 evbuffer_free(buf1);
2181 tt_int_op(evbuffer_remove(buf2, tmp, 6), ==, 6);
2182 tt_int_op(memcmp(tmp, "I have", 6), ==, 0);
2184 tt_int_op(evbuffer_remove(buf2, tmp, 6), ==, 6);
2185 tt_int_op(memcmp(tmp, " foun", 6), ==, 0);
2189 evbuffer_free(buf1);
2191 evbuffer_free(buf2);
2195 test_evbuffer_multicast_drain(void *ptr)
2197 const char chunk1[] = "If you have found the answer to such a problem";
2198 const char chunk2[] = "you ought to write it up for publication";
2199 /* -- Knuth's "Notes on the Exercises" from TAOCP */
2200 size_t len1 = strlen(chunk1), len2=strlen(chunk2);
2202 struct evbuffer *buf1 = NULL, *buf2 = NULL;
2204 buf1 = evbuffer_new();
2207 evbuffer_add(buf1, chunk1, len1);
2208 evbuffer_add(buf1, ", ", 2);
2209 evbuffer_add(buf1, chunk2, len2);
2210 tt_int_op(evbuffer_get_length(buf1), ==, len1+len2+2);
2212 buf2 = evbuffer_new();
2215 tt_int_op(evbuffer_add_buffer_reference(buf2, buf1), ==, 0);
2216 tt_int_op(evbuffer_get_length(buf2), ==, len1+len2+2);
2217 tt_int_op(evbuffer_drain(buf1, evbuffer_get_length(buf1)), ==, 0);
2218 tt_int_op(evbuffer_get_length(buf2), ==, len1+len2+2);
2219 tt_int_op(evbuffer_drain(buf2, evbuffer_get_length(buf2)), ==, 0);
2220 evbuffer_validate(buf1);
2221 evbuffer_validate(buf2);
2225 evbuffer_free(buf1);
2227 evbuffer_free(buf2);
2231 check_prepend(struct evbuffer *buffer,
2232 const struct evbuffer_cb_info *cbinfo,
2235 tt_int_op(cbinfo->orig_size, ==, 3);
2236 tt_int_op(cbinfo->n_added, ==, 8096);
2237 tt_int_op(cbinfo->n_deleted, ==, 0);
2241 /* Some cases that we didn't get in test_evbuffer() above, for more coverage. */
2243 test_evbuffer_prepend(void *ptr)
2245 struct evbuffer *buf1 = NULL, *buf2 = NULL;
2246 char tmp[128], *buffer = malloc(8096);
2249 buf1 = evbuffer_new();
2252 /* Case 0: The evbuffer is entirely empty. */
2253 evbuffer_prepend(buf1, "This string has 29 characters", 29);
2254 evbuffer_validate(buf1);
2256 /* Case 1: Prepend goes entirely in new chunk. */
2257 evbuffer_prepend(buf1, "Short.", 6);
2258 evbuffer_validate(buf1);
2260 /* Case 2: prepend goes entirely in first chunk. */
2261 evbuffer_drain(buf1, 6+11);
2262 evbuffer_prepend(buf1, "it", 2);
2263 evbuffer_validate(buf1);
2264 tt_assert(!memcmp(buf1->first->buffer+buf1->first->misalign,
2267 /* Case 3: prepend is split over multiple chunks. */
2268 evbuffer_prepend(buf1, "It is no longer true to say ", 28);
2269 evbuffer_validate(buf1);
2270 n = evbuffer_remove(buf1, tmp, sizeof(tmp)-1);
2271 tt_int_op(n, >=, 0);
2273 tt_str_op(tmp,==,"It is no longer true to say it has 29 characters");
2275 buf2 = evbuffer_new();
2278 /* Case 4: prepend a buffer to an empty buffer. */
2280 evbuffer_add_printf(buf1, "Here is string %d. ", n++);
2281 evbuffer_prepend_buffer(buf2, buf1);
2282 evbuffer_validate(buf2);
2284 /* Case 5: prepend a buffer to a nonempty buffer. */
2285 evbuffer_add_printf(buf1, "Here is string %d. ", n++);
2286 evbuffer_prepend_buffer(buf2, buf1);
2287 evbuffer_validate(buf2);
2288 evbuffer_validate(buf1);
2289 n = evbuffer_remove(buf2, tmp, sizeof(tmp)-1);
2290 tt_int_op(n, >=, 0);
2292 tt_str_op(tmp,==,"Here is string 1000. Here is string 999. ");
2294 /* Case 5: evbuffer_prepend() will need a new buffer, with callbacks */
2295 memset(buffer, 'A', 8096);
2296 evbuffer_free(buf2);
2297 buf2 = evbuffer_new();
2299 evbuffer_prepend(buf2, "foo", 3);
2300 evbuffer_add_cb(buf2, check_prepend, NULL);
2301 evbuffer_prepend(buf2, buffer, 8096);
2302 evbuffer_remove_cb(buf2, check_prepend, NULL);
2303 evbuffer_validate(buf2);
2304 tt_nstr_op(8096,(char *)evbuffer_pullup(buf2, 8096),==,buffer);
2305 evbuffer_drain(buf2, 8096);
2306 tt_nstr_op(3,(char *)evbuffer_pullup(buf2, 3),==,"foo");
2307 evbuffer_drain(buf2, 3);
2312 evbuffer_free(buf1);
2314 evbuffer_free(buf2);
2319 test_evbuffer_empty_reference_prepend(void *ptr)
2321 struct evbuffer *buf = NULL;
2323 buf = evbuffer_new();
2326 /** empty chain could leave invalid last_with_datap */
2327 evbuffer_add_reference(buf, "", 0, NULL, NULL);
2328 evbuffer_validate(buf);
2329 evbuffer_prepend(buf, "foo", 3);
2331 evbuffer_validate(buf);
2332 tt_assert(!strncmp((char *)evbuffer_pullup(buf, -1), "foo", 3));
2333 evbuffer_validate(buf);
2340 test_evbuffer_empty_reference_prepend_buffer(void *ptr)
2342 struct evbuffer *buf1 = NULL, *buf2 = NULL;
2344 buf1 = evbuffer_new();
2346 buf2 = evbuffer_new();
2349 /** empty chain could leave invalid last_with_datap */
2350 evbuffer_add_reference(buf1, "", 0, NULL, NULL);
2351 evbuffer_validate(buf1);
2352 evbuffer_add(buf2, "foo", 3);
2353 evbuffer_validate(buf2);
2354 evbuffer_prepend_buffer(buf2, buf1);
2355 evbuffer_validate(buf2);
2357 tt_assert(!strncmp((char *)evbuffer_pullup(buf2, -1), "foo", 3));
2358 evbuffer_validate(buf2);
2360 tt_assert(evbuffer_pullup(buf1, -1) == NULL);
2361 evbuffer_validate(buf2);
2365 evbuffer_free(buf1);
2367 evbuffer_free(buf2);
2371 test_evbuffer_peek_first_gt(void *info)
2373 struct evbuffer *buf = NULL, *tmp_buf = NULL;
2374 struct evbuffer_ptr ptr;
2375 struct evbuffer_iovec v[2];
2377 buf = evbuffer_new();
2378 tmp_buf = evbuffer_new();
2379 evbuffer_add_printf(tmp_buf, "Contents of chunk 100\n");
2380 evbuffer_add_buffer(buf, tmp_buf);
2381 evbuffer_add_printf(tmp_buf, "Contents of chunk 1\n");
2382 evbuffer_add_buffer(buf, tmp_buf);
2384 evbuffer_ptr_set(buf, &ptr, 0, EVBUFFER_PTR_SET);
2386 /** The only case that matters*/
2387 tt_int_op(evbuffer_peek(buf, -1, &ptr, NULL, 0), ==, 2);
2389 tt_int_op(evbuffer_peek(buf, -1, &ptr, v, 2), ==, 2);
2391 evbuffer_ptr_set(buf, &ptr, 20, EVBUFFER_PTR_ADD);
2392 tt_int_op(evbuffer_peek(buf, -1, &ptr, NULL, 0), ==, 2);
2393 tt_int_op(evbuffer_peek(buf, -1, &ptr, v, 2), ==, 2);
2394 tt_int_op(evbuffer_peek(buf, 2, &ptr, NULL, 0), ==, 1);
2395 tt_int_op(evbuffer_peek(buf, 2, &ptr, v, 2), ==, 1);
2396 tt_int_op(evbuffer_peek(buf, 3, &ptr, NULL, 0), ==, 2);
2397 tt_int_op(evbuffer_peek(buf, 3, &ptr, v, 2), ==, 2);
2403 evbuffer_free(tmp_buf);
2407 test_evbuffer_peek(void *info)
2409 struct evbuffer *buf = NULL, *tmp_buf = NULL;
2411 struct evbuffer_iovec v[20];
2412 struct evbuffer_ptr ptr;
2414 #define tt_iov_eq(v, s) \
2415 tt_int_op((v)->iov_len, ==, strlen(s)); \
2416 tt_assert(!memcmp((v)->iov_base, (s), strlen(s)))
2418 /* Let's make a very fragmented buffer. */
2419 buf = evbuffer_new();
2420 tmp_buf = evbuffer_new();
2421 for (i = 0; i < 16; ++i) {
2422 evbuffer_add_printf(tmp_buf, "Contents of chunk [%d]\n", i);
2423 evbuffer_add_buffer(buf, tmp_buf);
2426 /* How many chunks do we need for everything? */
2427 i = evbuffer_peek(buf, -1, NULL, NULL, 0);
2428 tt_int_op(i, ==, 16);
2430 /* Simple peek: get everything. */
2431 i = evbuffer_peek(buf, -1, NULL, v, 20);
2432 tt_int_op(i, ==, 16); /* we used only 16 chunks. */
2433 tt_iov_eq(&v[0], "Contents of chunk [0]\n");
2434 tt_iov_eq(&v[3], "Contents of chunk [3]\n");
2435 tt_iov_eq(&v[12], "Contents of chunk [12]\n");
2436 tt_iov_eq(&v[15], "Contents of chunk [15]\n");
2438 /* Just get one chunk worth. */
2439 memset(v, 0, sizeof(v));
2440 i = evbuffer_peek(buf, -1, NULL, v, 1);
2441 tt_int_op(i, ==, 1);
2442 tt_iov_eq(&v[0], "Contents of chunk [0]\n");
2443 tt_assert(v[1].iov_base == NULL);
2445 /* Suppose we want at least the first 40 bytes. */
2446 memset(v, 0, sizeof(v));
2447 i = evbuffer_peek(buf, 40, NULL, v, 16);
2448 tt_int_op(i, ==, 2);
2449 tt_iov_eq(&v[0], "Contents of chunk [0]\n");
2450 tt_iov_eq(&v[1], "Contents of chunk [1]\n");
2451 tt_assert(v[2].iov_base == NULL);
2453 /* How many chunks do we need for 100 bytes? */
2454 memset(v, 0, sizeof(v));
2455 i = evbuffer_peek(buf, 100, NULL, NULL, 0);
2456 tt_int_op(i, ==, 5);
2457 tt_assert(v[0].iov_base == NULL);
2459 /* Now we ask for more bytes than we provide chunks for */
2460 memset(v, 0, sizeof(v));
2461 i = evbuffer_peek(buf, 60, NULL, v, 1);
2462 tt_int_op(i, ==, 3);
2463 tt_iov_eq(&v[0], "Contents of chunk [0]\n");
2464 tt_assert(v[1].iov_base == NULL);
2466 /* Now we ask for more bytes than the buffer has. */
2467 memset(v, 0, sizeof(v));
2468 i = evbuffer_peek(buf, 65536, NULL, v, 20);
2469 tt_int_op(i, ==, 16); /* we used only 16 chunks. */
2470 tt_iov_eq(&v[0], "Contents of chunk [0]\n");
2471 tt_iov_eq(&v[3], "Contents of chunk [3]\n");
2472 tt_iov_eq(&v[12], "Contents of chunk [12]\n");
2473 tt_iov_eq(&v[15], "Contents of chunk [15]\n");
2474 tt_assert(v[16].iov_base == NULL);
2476 /* What happens if we try an empty buffer? */
2477 memset(v, 0, sizeof(v));
2478 i = evbuffer_peek(tmp_buf, -1, NULL, v, 20);
2479 tt_int_op(i, ==, 0);
2480 tt_assert(v[0].iov_base == NULL);
2481 memset(v, 0, sizeof(v));
2482 i = evbuffer_peek(tmp_buf, 50, NULL, v, 20);
2483 tt_int_op(i, ==, 0);
2484 tt_assert(v[0].iov_base == NULL);
2486 /* Okay, now time to have fun with pointers. */
2487 memset(v, 0, sizeof(v));
2488 evbuffer_ptr_set(buf, &ptr, 30, EVBUFFER_PTR_SET);
2489 i = evbuffer_peek(buf, 50, &ptr, v, 20);
2490 tt_int_op(i, ==, 3);
2491 tt_iov_eq(&v[0], " of chunk [1]\n");
2492 tt_iov_eq(&v[1], "Contents of chunk [2]\n");
2493 tt_iov_eq(&v[2], "Contents of chunk [3]\n"); /*more than we asked for*/
2495 /* advance to the start of another chain. */
2496 memset(v, 0, sizeof(v));
2497 evbuffer_ptr_set(buf, &ptr, 14, EVBUFFER_PTR_ADD);
2498 i = evbuffer_peek(buf, 44, &ptr, v, 20);
2499 tt_int_op(i, ==, 2);
2500 tt_iov_eq(&v[0], "Contents of chunk [2]\n");
2501 tt_iov_eq(&v[1], "Contents of chunk [3]\n"); /*more than we asked for*/
2503 /* peek at the end of the buffer */
2504 memset(v, 0, sizeof(v));
2505 tt_assert(evbuffer_ptr_set(buf, &ptr, evbuffer_get_length(buf), EVBUFFER_PTR_SET) == 0);
2506 i = evbuffer_peek(buf, 44, &ptr, v, 20);
2507 tt_int_op(i, ==, 0);
2508 tt_assert(v[0].iov_base == NULL);
2514 evbuffer_free(tmp_buf);
2517 /* Check whether evbuffer freezing works right. This is called twice,
2518 once with the argument "start" and once with the argument "end".
2519 When we test "start", we freeze the start of an evbuffer and make sure
2520 that modifying the start of the buffer doesn't work. When we test
2521 "end", we freeze the end of an evbuffer and make sure that modifying
2522 the end of the buffer doesn't work.
2525 test_evbuffer_freeze(void *ptr)
2527 struct basic_test_data *testdata = ptr;
2528 evutil_socket_t *pair = testdata->pair;
2529 struct evbuffer *buf = NULL, *buf_two = NULL, *tmp_buf = NULL;
2530 const char string[] = /* Year's End, Richard Wilbur */
2531 "I've known the wind by water banks to shake\n"
2532 "The late leaves down, which frozen where they fell\n"
2533 "And held in ice as dancers in a spell\n"
2534 "Fluttered all winter long into a lake...";
2535 const int start = !strcmp(testdata->setup_data, "start");
2536 const char tmpfilecontent[] = "file_freeze_test_file";
2539 char *tmpfilename = NULL;
2542 size_t orig_length, len;
2543 struct evbuffer_iovec v[1];
2546 tt_str_op(testdata->setup_data, ==, "end");
2548 buf = evbuffer_new();
2549 buf_two = evbuffer_new();
2550 tmp_buf = evbuffer_new();
2553 evbuffer_add(buf, string, strlen(string));
2554 evbuffer_add(buf_two, "abc", 3);
2555 evbuffer_add(tmp_buf, "xyz", 3);
2556 evbuffer_freeze(buf, start); /* Freeze the start or the end.*/
2557 evbuffer_freeze(buf_two, start);
2559 #define FREEZE_EQ(a, startcase, endcase) \
2562 tt_int_op((a), ==, (startcase)); \
2564 tt_int_op((a), ==, (endcase)); \
2569 orig_length = evbuffer_get_length(buf);
2571 /* These functions all manipulate the end of buf. */
2572 r = evbuffer_add(buf, "abc", 0);
2573 FREEZE_EQ(r, 0, -1);
2574 r = evbuffer_reserve_space(buf, 10, v, 1);
2575 FREEZE_EQ(r, 1, -1);
2577 memset(v[0].iov_base, 'X', 10);
2580 r = evbuffer_commit_space(buf, v, 1);
2581 FREEZE_EQ(r, 0, -1);
2582 r = evbuffer_add_reference(buf, string, 5, NULL, NULL);
2583 FREEZE_EQ(r, 0, -1);
2584 r = evbuffer_add_printf(buf, "Hello %s", "world");
2585 FREEZE_EQ(r, 11, -1);
2587 r = evbuffer_add_buffer(buf, tmp_buf);
2588 FREEZE_EQ(r, 0, -1);
2589 len = strlen(tmpfilecontent);
2590 fd = regress_make_tmpfile(tmpfilecontent, len, &tmpfilename);
2591 r = evbuffer_add_file(buf, fd, 0, len);
2592 FREEZE_EQ(r, 0, -1);
2595 evbuffer_add(tmp_buf, "xyz", 3);
2597 tt_assert(evbuffer_get_length(tmp_buf));
2598 len = evbuffer_get_length(tmp_buf);
2599 evbuffer_write(tmp_buf, pair[0]);
2600 r = evbuffer_read(buf, pair[1], -1);
2601 FREEZE_EQ(r, len, -1);
2604 tt_int_op(orig_length, ==, evbuffer_get_length(buf));
2606 orig_length = evbuffer_get_length(buf);
2608 /* These functions all manipulate the start of buf. */
2609 r = evbuffer_remove(buf, charbuf, 1);
2610 FREEZE_EQ(r, -1, 1);
2611 r = evbuffer_drain(buf, 3);
2612 FREEZE_EQ(r, -1, 0);
2613 r = evbuffer_prepend(buf, "dummy", 5);
2614 FREEZE_EQ(r, -1, 0);
2615 cp = evbuffer_readln(buf, NULL, EVBUFFER_EOL_LF);
2616 FREEZE_EQ(cp==NULL, 1, 0);
2620 evbuffer_add(tmp_buf, "xyz", 3);
2621 tt_assert(evbuffer_get_length(tmp_buf));
2622 r = evbuffer_remove_buffer(buf, tmp_buf, 3);
2623 FREEZE_EQ(r, -1, 3);
2624 r = evbuffer_drain(buf, 3);
2625 FREEZE_EQ(r, -1, 0);
2626 r = evbuffer_prepend_buffer(buf, tmp_buf);
2627 FREEZE_EQ(r, -1, 0);
2629 len = evbuffer_get_length(buf);
2630 r = evbuffer_write(buf, pair[0]);
2631 evbuffer_read(tmp_buf, pair[1], -1);
2632 FREEZE_EQ(r, -1, len);
2633 len = evbuffer_get_length(buf_two);
2634 r = evbuffer_write_atmost(buf_two, pair[0], -1);
2635 evbuffer_read(tmp_buf, pair[1], -1);
2636 FREEZE_EQ(r, -1, len);
2639 tt_int_op(orig_length, ==, evbuffer_get_length(buf));
2646 evbuffer_free(buf_two);
2649 evbuffer_free(tmp_buf);
2652 unlink(tmpfilename);
2658 test_evbuffer_add_iovec(void * ptr)
2660 struct evbuffer * buf = NULL;
2661 struct evbuffer_iovec vec[4];
2662 const char * data[] = {
2663 "Guilt resembles a sword with two edges.",
2664 "On the one hand, it cuts for Justice, imposing practical morality upon those who fear it.",
2665 "Conscience does not always adhere to rational judgment.",
2666 "Guilt is always a self-imposed burden, but it is not always rightly imposed."
2667 /* -- R.A. Salvatore, _Sojurn_ */
2669 size_t expected_length = 0;
2670 size_t returned_length = 0;
2673 buf = evbuffer_new();
2677 for (i = 0; i < 4; i++) {
2678 vec[i].iov_len = strlen(data[i]);
2679 vec[i].iov_base = (char*) data[i];
2680 expected_length += vec[i].iov_len;
2683 returned_length = evbuffer_add_iovec(buf, vec, 4);
2685 tt_int_op(returned_length, ==, evbuffer_get_length(buf));
2686 tt_int_op(evbuffer_get_length(buf), ==, expected_length);
2688 for (i = 0; i < 4; i++) {
2691 memset(charbuf, 0, 1024);
2692 evbuffer_remove(buf, charbuf, strlen(data[i]));
2693 tt_assert(strcmp(charbuf, data[i]) == 0);
2696 tt_assert(evbuffer_get_length(buf) == 0);
2704 test_evbuffer_copyout(void *dummy)
2706 const char string[] =
2707 "Still they skirmish to and fro, men my messmates on the snow "
2708 "When we headed off the aurochs turn for turn; "
2709 "When the rich Allobrogenses never kept amanuenses, "
2710 "And our only plots were piled in lakes at Berne.";
2711 /* -- Kipling, "In The Neolithic Age" */
2713 struct evbuffer_ptr ptr;
2714 struct evbuffer *buf;
2718 buf = evbuffer_new();
2721 tt_int_op(strlen(string), ==, 206);
2723 /* Ensure separate chains */
2724 evbuffer_add_reference(buf, string, 80, no_cleanup, NULL);
2725 evbuffer_add_reference(buf, string+80, 80, no_cleanup, NULL);
2726 evbuffer_add(buf, string+160, strlen(string)-160);
2728 tt_int_op(206, ==, evbuffer_get_length(buf));
2730 /* First, let's test plain old copyout. */
2732 /* Copy a little from the beginning. */
2733 tt_int_op(10, ==, evbuffer_copyout(buf, tmp, 10));
2734 tt_int_op(0, ==, memcmp(tmp, "Still they", 10));
2736 /* Now copy more than a little from the beginning */
2737 memset(tmp, 0, sizeof(tmp));
2738 tt_int_op(100, ==, evbuffer_copyout(buf, tmp, 100));
2739 tt_int_op(0, ==, memcmp(tmp, string, 100));
2741 /* Copy too much; ensure truncation. */
2742 memset(tmp, 0, sizeof(tmp));
2743 tt_int_op(206, ==, evbuffer_copyout(buf, tmp, 230));
2744 tt_int_op(0, ==, memcmp(tmp, string, 206));
2746 /* That was supposed to be nondestructive, btw */
2747 tt_int_op(206, ==, evbuffer_get_length(buf));
2749 /* Now it's time to test copyout_from! First, let's start in the
2751 evbuffer_ptr_set(buf, &ptr, 15, EVBUFFER_PTR_SET);
2752 memset(tmp, 0, sizeof(tmp));
2753 tt_int_op(10, ==, evbuffer_copyout_from(buf, &ptr, tmp, 10));
2754 tt_int_op(0, ==, memcmp(tmp, "mish to an", 10));
2756 /* Right up to the end of the first chain */
2757 memset(tmp, 0, sizeof(tmp));
2758 tt_int_op(65, ==, evbuffer_copyout_from(buf, &ptr, tmp, 65));
2759 tt_int_op(0, ==, memcmp(tmp, string+15, 65));
2761 /* Span into the second chain */
2762 memset(tmp, 0, sizeof(tmp));
2763 tt_int_op(90, ==, evbuffer_copyout_from(buf, &ptr, tmp, 90));
2764 tt_int_op(0, ==, memcmp(tmp, string+15, 90));
2766 /* Span into the third chain */
2767 memset(tmp, 0, sizeof(tmp));
2768 tt_int_op(160, ==, evbuffer_copyout_from(buf, &ptr, tmp, 160));
2769 tt_int_op(0, ==, memcmp(tmp, string+15, 160));
2772 memset(tmp, 0, sizeof(tmp));
2773 tt_int_op(206-15, ==, evbuffer_copyout_from(buf, &ptr, tmp, 999));
2774 tt_int_op(0, ==, memcmp(tmp, string+15, 206-15));
2776 /* That was supposed to be nondestructive, too */
2777 tt_int_op(206, ==, evbuffer_get_length(buf));
2785 setup_passthrough(const struct testcase_t *testcase)
2787 return testcase->setup_data;
2790 cleanup_passthrough(const struct testcase_t *testcase, void *ptr)
2796 static const struct testcase_setup_t nil_setup = {
2801 struct testcase_t evbuffer_testcases[] = {
2802 { "evbuffer", test_evbuffer, 0, NULL, NULL },
2803 { "remove_buffer_with_empty", test_evbuffer_remove_buffer_with_empty, 0, NULL, NULL },
2804 { "remove_buffer_with_empty2", test_evbuffer_remove_buffer_with_empty2, 0, NULL, NULL },
2805 { "remove_buffer_with_empty3", test_evbuffer_remove_buffer_with_empty3, 0, NULL, NULL },
2806 { "remove_buffer_with_empty_front", test_evbuffer_remove_buffer_with_empty_front, 0, NULL, NULL },
2807 { "remove_buffer_adjust_last_with_datap_with_empty",
2808 test_evbuffer_remove_buffer_adjust_last_with_datap_with_empty, 0, NULL, NULL },
2809 { "add_buffer_with_empty", test_evbuffer_add_buffer_with_empty, 0, NULL, NULL },
2810 { "add_buffer_with_empty2", test_evbuffer_add_buffer_with_empty2, 0, NULL, NULL },
2811 { "reserve2", test_evbuffer_reserve2, 0, NULL, NULL },
2812 { "reserve_many", test_evbuffer_reserve_many, 0, NULL, NULL },
2813 { "reserve_many2", test_evbuffer_reserve_many, 0, &nil_setup, (void*)"add" },
2814 { "reserve_many3", test_evbuffer_reserve_many, 0, &nil_setup, (void*)"fill" },
2815 { "reserve_with_empty", test_evbuffer_reserve_with_empty, 0, NULL, NULL },
2816 { "reserve_invalid_last_with_datap", test_evbuffer_reserve_invalid_last_with_datap, TT_FORK, NULL, NULL },
2817 { "expand", test_evbuffer_expand, 0, NULL, NULL },
2818 { "expand_overflow", test_evbuffer_expand_overflow, 0, NULL, NULL },
2819 { "add1", test_evbuffer_add1, 0, NULL, NULL },
2820 { "add2", test_evbuffer_add2, 0, NULL, NULL },
2821 { "reference", test_evbuffer_reference, 0, NULL, NULL },
2822 { "reference2", test_evbuffer_reference2, 0, NULL, NULL },
2823 { "iterative", test_evbuffer_iterative, 0, NULL, NULL },
2824 { "readln", test_evbuffer_readln, TT_NO_LOGS, &basic_setup, NULL },
2825 { "search_eol", test_evbuffer_search_eol, 0, NULL, NULL },
2826 { "find", test_evbuffer_find, 0, NULL, NULL },
2827 { "ptr_set", test_evbuffer_ptr_set, 0, NULL, NULL },
2828 { "search", test_evbuffer_search, 0, NULL, NULL },
2829 { "callbacks", test_evbuffer_callbacks, 0, NULL, NULL },
2830 { "add_reference", test_evbuffer_add_reference, 0, NULL, NULL },
2831 { "multicast", test_evbuffer_multicast, 0, NULL, NULL },
2832 { "multicast_drain", test_evbuffer_multicast_drain, 0, NULL, NULL },
2833 { "prepend", test_evbuffer_prepend, TT_FORK, NULL, NULL },
2834 { "empty_reference_prepend", test_evbuffer_empty_reference_prepend, TT_FORK, NULL, NULL },
2835 { "empty_reference_prepend_buffer", test_evbuffer_empty_reference_prepend_buffer, TT_FORK, NULL, NULL },
2836 { "peek", test_evbuffer_peek, 0, NULL, NULL },
2837 { "peek_first_gt", test_evbuffer_peek_first_gt, 0, NULL, NULL },
2838 { "freeze_start", test_evbuffer_freeze, TT_NEED_SOCKETPAIR, &basic_setup, (void*)"start" },
2839 { "freeze_end", test_evbuffer_freeze, TT_NEED_SOCKETPAIR, &basic_setup, (void*)"end" },
2840 { "add_iovec", test_evbuffer_add_iovec, 0, NULL, NULL},
2841 { "copyout", test_evbuffer_copyout, 0, NULL, NULL},
2842 { "file_segment_add_cleanup_cb", test_evbuffer_file_segment_add_cleanup_cb, 0, NULL, NULL },
2843 { "pullup_with_empty", test_evbuffer_pullup_with_empty, 0, NULL, NULL },
2845 #define ADDFILE_TEST(name, parameters) \
2846 { name, test_evbuffer_add_file, TT_FORK|TT_NEED_BASE, \
2847 &basic_setup, (void*)(parameters) }
2849 #define ADDFILE_TEST_GROUP(name, parameters) \
2850 ADDFILE_TEST(name "_sendfile", "sendfile " parameters), \
2851 ADDFILE_TEST(name "_mmap", "mmap " parameters), \
2852 ADDFILE_TEST(name "_linear", "linear " parameters)
2854 ADDFILE_TEST_GROUP("add_file", ""),
2855 ADDFILE_TEST("add_file_nosegment", "default nosegment"),
2857 ADDFILE_TEST_GROUP("add_big_file", "bigfile"),
2858 ADDFILE_TEST("add_big_file_nosegment", "default nosegment bigfile"),
2860 ADDFILE_TEST_GROUP("add_file_offset", "bigfile map_offset"),
2861 ADDFILE_TEST("add_file_offset_nosegment",
2862 "default nosegment bigfile map_offset"),
2864 ADDFILE_TEST_GROUP("add_file_offset2", "bigfile offset_in_segment"),
2866 ADDFILE_TEST_GROUP("add_file_offset3",
2867 "bigfile offset_in_segment map_offset"),