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 /* Validates that an evbuffer is good. Returns false if it isn't, true if it
69 evbuffer_validate_(struct evbuffer *buf)
71 struct evbuffer_chain *chain;
73 int found_last_with_datap = 0;
75 if (buf->first == NULL) {
76 tt_assert(buf->last == NULL);
77 tt_assert(buf->total_len == 0);
82 tt_assert(buf->last_with_datap);
83 if (buf->last_with_datap == &buf->first)
84 found_last_with_datap = 1;
86 while (chain != NULL) {
87 if (&chain->next == buf->last_with_datap)
88 found_last_with_datap = 1;
90 if (chain->next == NULL) {
91 tt_assert(buf->last == chain);
93 tt_assert(chain->buffer_len >= chain->misalign + chain->off);
98 tt_assert(*buf->last_with_datap);
100 if (*buf->last_with_datap) {
101 chain = *buf->last_with_datap;
102 if (chain->off == 0 || buf->total_len == 0) {
103 tt_assert(chain->off == 0)
104 tt_assert(chain == buf->first);
105 tt_assert(buf->total_len == 0);
108 while (chain != NULL) {
109 tt_assert(chain->off == 0);
113 tt_assert(buf->last_with_datap == &buf->first);
115 tt_assert(found_last_with_datap);
117 tt_assert(sum == buf->total_len);
124 evbuffer_get_waste(struct evbuffer *buf, size_t *allocatedp, size_t *wastedp, size_t *usedp)
126 struct evbuffer_chain *chain;
132 /* skip empty at start */
133 while (chain && chain->off==0) {
135 a += chain->buffer_len;
138 /* first nonempty chain: stuff at the end only is wasted. */
141 a += chain->buffer_len;
143 if (chain->next && chain->next->off)
144 w += (size_t)(chain->buffer_len - (chain->misalign + chain->off));
147 /* subsequent nonempty chains */
148 while (chain && chain->off) {
150 a += chain->buffer_len;
151 w += (size_t)chain->misalign;
153 if (chain->next && chain->next->off)
154 w += (size_t) (chain->buffer_len - (chain->misalign + chain->off));
157 /* subsequent empty chains */
160 a += chain->buffer_len;
167 #define evbuffer_validate(buf) \
168 TT_STMT_BEGIN if (!evbuffer_validate_(buf)) TT_DIE(("Buffer format invalid")); TT_STMT_END
171 test_evbuffer(void *ptr)
173 static char buffer[512], *tmp;
174 struct evbuffer *evb = evbuffer_new();
175 struct evbuffer *evb_two = evbuffer_new();
179 evbuffer_validate(evb);
180 evbuffer_add_printf(evb, "%s/%d", "hello", 1);
181 evbuffer_validate(evb);
183 tt_assert(evbuffer_get_length(evb) == 7);
184 tt_assert(!memcmp((char*)EVBUFFER_DATA(evb), "hello/1", 1));
186 evbuffer_add_buffer(evb, evb_two);
187 evbuffer_validate(evb);
189 evbuffer_drain(evb, strlen("hello/"));
190 evbuffer_validate(evb);
191 tt_assert(evbuffer_get_length(evb) == 1);
192 tt_assert(!memcmp((char*)EVBUFFER_DATA(evb), "1", 1));
194 evbuffer_add_printf(evb_two, "%s", "/hello");
195 evbuffer_validate(evb);
196 evbuffer_add_buffer(evb, evb_two);
197 evbuffer_validate(evb);
199 tt_assert(evbuffer_get_length(evb_two) == 0);
200 tt_assert(evbuffer_get_length(evb) == 7);
201 tt_assert(!memcmp((char*)EVBUFFER_DATA(evb), "1/hello", 7) != 0);
203 memset(buffer, 0, sizeof(buffer));
204 evbuffer_add(evb, buffer, sizeof(buffer));
205 evbuffer_validate(evb);
206 tt_assert(evbuffer_get_length(evb) == 7 + 512);
208 tmp = (char *)evbuffer_pullup(evb, 7 + 512);
210 tt_assert(!strncmp(tmp, "1/hello", 7));
211 tt_assert(!memcmp(tmp + 7, buffer, sizeof(buffer)));
212 evbuffer_validate(evb);
214 evbuffer_prepend(evb, "something", 9);
215 evbuffer_validate(evb);
216 evbuffer_prepend(evb, "else", 4);
217 evbuffer_validate(evb);
219 tmp = (char *)evbuffer_pullup(evb, 4 + 9 + 7);
220 tt_assert(!strncmp(tmp, "elsesomething1/hello", 4 + 9 + 7));
221 evbuffer_validate(evb);
223 evbuffer_drain(evb, -1);
224 evbuffer_validate(evb);
225 evbuffer_drain(evb_two, -1);
226 evbuffer_validate(evb);
228 for (i = 0; i < 3; ++i) {
229 evbuffer_add(evb_two, buffer, sizeof(buffer));
230 evbuffer_validate(evb_two);
231 evbuffer_add_buffer(evb, evb_two);
232 evbuffer_validate(evb);
233 evbuffer_validate(evb_two);
236 tt_assert(evbuffer_get_length(evb_two) == 0);
237 tt_assert(evbuffer_get_length(evb) == i * sizeof(buffer));
239 /* test remove buffer */
240 sz_tmp = (size_t)(sizeof(buffer)*2.5);
241 evbuffer_remove_buffer(evb, evb_two, sz_tmp);
242 tt_assert(evbuffer_get_length(evb_two) == sz_tmp);
243 tt_assert(evbuffer_get_length(evb) == sizeof(buffer) / 2);
244 evbuffer_validate(evb);
246 if (memcmp(evbuffer_pullup(
247 evb, -1), buffer, sizeof(buffer) / 2) != 0 ||
248 memcmp(evbuffer_pullup(
249 evb_two, -1), buffer, sizeof(buffer)) != 0)
250 tt_abort_msg("Pullup did not preserve content");
252 evbuffer_validate(evb);
255 /* testing one-vector reserve and commit */
257 struct evbuffer_iovec v[1];
261 for (i = 0; i < 3; ++i) {
262 r = evbuffer_reserve_space(evb, 10000, v, 1);
264 tt_assert(v[0].iov_len >= 10000);
265 tt_assert(v[0].iov_base != NULL);
267 evbuffer_validate(evb);
269 for (j = 0; j < 10000; ++j) {
272 evbuffer_validate(evb);
274 tt_int_op(evbuffer_commit_space(evb, v, 1), ==, 0);
275 evbuffer_validate(evb);
277 tt_assert(evbuffer_get_length(evb) >= 10000);
279 evbuffer_drain(evb, j * 5000);
280 evbuffer_validate(evb);
286 evbuffer_free(evb_two);
290 no_cleanup(const void *data, size_t datalen, void *extra)
295 test_evbuffer_remove_buffer_with_empty(void *ptr)
297 struct evbuffer *src = evbuffer_new();
298 struct evbuffer *dst = evbuffer_new();
301 evbuffer_validate(src);
302 evbuffer_validate(dst);
304 /* setup the buffers */
305 /* we need more data in src than we will move later */
306 evbuffer_add_reference(src, buf, sizeof(buf), no_cleanup, NULL);
307 evbuffer_add_reference(src, buf, sizeof(buf), no_cleanup, NULL);
308 /* we need one buffer in dst and one empty buffer at the end */
309 evbuffer_add(dst, buf, sizeof(buf));
310 evbuffer_add_reference(dst, buf, 0, no_cleanup, NULL);
312 evbuffer_validate(src);
313 evbuffer_validate(dst);
315 /* move three bytes over */
316 evbuffer_remove_buffer(src, dst, 3);
318 evbuffer_validate(src);
319 evbuffer_validate(dst);
327 test_evbuffer_reserve2(void *ptr)
329 /* Test the two-vector cases of reserve/commit. */
330 struct evbuffer *buf = evbuffer_new();
332 struct evbuffer_iovec v[2];
336 /* First chunk will necessarily be one chunk. Use 512 bytes of it.*/
337 n = evbuffer_reserve_space(buf, 1024, v, 2);
339 tt_int_op(evbuffer_get_length(buf), ==, 0);
340 tt_assert(v[0].iov_base != NULL);
341 tt_int_op(v[0].iov_len, >=, 1024);
342 memset(v[0].iov_base, 'X', 512);
344 remaining = v[0].iov_len - 512;
346 evbuffer_validate(buf);
347 tt_int_op(0, ==, evbuffer_commit_space(buf, v, 1));
348 tt_int_op(evbuffer_get_length(buf), ==, 512);
349 evbuffer_validate(buf);
351 /* Ask for another same-chunk request, in an existing chunk. Use 8
353 n = evbuffer_reserve_space(buf, 32, v, 2);
355 tt_assert(cp + 512 == v[0].iov_base);
356 tt_int_op(remaining, ==, v[0].iov_len);
357 memset(v[0].iov_base, 'Y', 8);
359 tt_int_op(0, ==, evbuffer_commit_space(buf, v, 1));
360 tt_int_op(evbuffer_get_length(buf), ==, 520);
362 evbuffer_validate(buf);
364 /* Now ask for a request that will be split. Use only one byte of it,
366 n = evbuffer_reserve_space(buf, remaining+64, v, 2);
368 tt_assert(cp + 520 == v[0].iov_base);
369 tt_int_op(remaining, ==, v[0].iov_len);
370 tt_assert(v[1].iov_base);
371 tt_assert(v[1].iov_len >= 64);
373 memset(v[0].iov_base, 'Z', 1);
375 tt_int_op(0, ==, evbuffer_commit_space(buf, v, 1));
376 tt_int_op(evbuffer_get_length(buf), ==, 521);
378 evbuffer_validate(buf);
380 /* Now ask for a request that will be split. Use some of the first
381 * part and some of the second. */
382 n = evbuffer_reserve_space(buf, remaining+64, v, 2);
383 evbuffer_validate(buf);
385 tt_assert(cp + 521 == v[0].iov_base);
386 tt_int_op(remaining, ==, v[0].iov_len);
387 tt_assert(v[1].iov_base == cp2);
388 tt_assert(v[1].iov_len >= 64);
389 memset(v[0].iov_base, 'W', 400);
391 memset(v[1].iov_base, 'x', 60);
393 tt_int_op(0, ==, evbuffer_commit_space(buf, v, 2));
394 tt_int_op(evbuffer_get_length(buf), ==, 981);
395 evbuffer_validate(buf);
397 /* Now peek to make sure stuff got made how we like. */
398 memset(v,0,sizeof(v));
399 n = evbuffer_peek(buf, -1, NULL, v, 2);
401 tt_int_op(v[0].iov_len, ==, 921);
402 tt_int_op(v[1].iov_len, ==, 60);
405 for (i=0; i<512; ++i)
406 tt_int_op(cp[i], ==, 'X');
407 for (i=512; i<520; ++i)
408 tt_int_op(cp[i], ==, 'Y');
409 for (i=520; i<521; ++i)
410 tt_int_op(cp[i], ==, 'Z');
411 for (i=521; i<921; ++i)
412 tt_int_op(cp[i], ==, 'W');
416 tt_int_op(cp[i], ==, 'x');
423 test_evbuffer_reserve_many(void *ptr)
425 /* This is a glass-box test to handle expanding a buffer with more
426 * chunks and reallocating chunks as needed */
427 struct evbuffer *buf = evbuffer_new();
428 struct evbuffer_iovec v[8];
431 int add_data = ptr && !strcmp(ptr, "add");
432 int fill_first = ptr && !strcmp(ptr, "fill");
435 /* When reserving the the first chunk, we just allocate it */
436 n = evbuffer_reserve_space(buf, 128, v, 2);
437 evbuffer_validate(buf);
439 tt_assert(v[0].iov_len >= 128);
443 *(char*)v[0].iov_base = 'X';
445 n = evbuffer_commit_space(buf, v, 1);
447 } else if (fill_first) {
448 memset(v[0].iov_base, 'X', v[0].iov_len);
449 n = evbuffer_commit_space(buf, v, 1);
451 n = evbuffer_reserve_space(buf, 128, v, 2);
454 tt_assert(v[0].iov_base != cp1);
458 /* Make another chunk get added. */
459 n = evbuffer_reserve_space(buf, sz+128, v, 2);
460 evbuffer_validate(buf);
462 sz = v[0].iov_len + v[1].iov_len;
463 tt_int_op(sz, >=, v[0].iov_len+128);
465 tt_assert(v[0].iov_base == cp1 + 1);
467 tt_assert(v[0].iov_base == cp1);
472 /* And a third chunk. */
473 n = evbuffer_reserve_space(buf, sz+128, v, 3);
474 evbuffer_validate(buf);
476 tt_assert(cp1 == v[0].iov_base);
477 tt_assert(cp2 == v[1].iov_base);
478 sz = v[0].iov_len + v[1].iov_len + v[2].iov_len;
480 /* Now force a reallocation by asking for more space in only 2
482 n = evbuffer_reserve_space(buf, sz+128, v, 2);
483 evbuffer_validate(buf);
486 tt_assert(cp1 == v[0].iov_base);
496 test_evbuffer_expand(void *ptr)
499 struct evbuffer *buf;
503 memset(data, 'X', sizeof(data));
505 /* Make sure that expand() works on an empty buffer */
506 buf = evbuffer_new();
507 tt_int_op(evbuffer_expand(buf, 20000), ==, 0);
508 evbuffer_validate(buf);
510 evbuffer_get_waste(buf, &a,&w,&u);
513 tt_assert(a >= 20000);
514 tt_assert(buf->first);
515 tt_assert(buf->first == buf->last);
516 tt_assert(buf->first->off == 0);
517 tt_assert(buf->first->buffer_len >= 20000);
519 /* Make sure that expand() works as a no-op when there's enough
520 * contiguous space already. */
521 buffer = buf->first->buffer;
522 evbuffer_add(buf, data, 1024);
523 tt_int_op(evbuffer_expand(buf, 1024), ==, 0);
524 tt_assert(buf->first->buffer == buffer);
525 evbuffer_validate(buf);
528 /* Make sure that expand() can work by moving misaligned data
529 * when it makes sense to do so. */
530 buf = evbuffer_new();
531 evbuffer_add(buf, data, 400);
533 int n = (int)(buf->first->buffer_len - buf->first->off - 1);
534 tt_assert(n < (int)sizeof(data));
535 evbuffer_add(buf, data, n);
537 tt_assert(buf->first == buf->last);
538 tt_assert(buf->first->off == buf->first->buffer_len - 1);
539 evbuffer_drain(buf, buf->first->off - 1);
540 tt_assert(1 == evbuffer_get_length(buf));
541 tt_assert(buf->first->misalign > 0);
542 tt_assert(buf->first->off == 1);
543 buffer = buf->first->buffer;
544 tt_assert(evbuffer_expand(buf, 40) == 0);
545 tt_assert(buf->first == buf->last);
546 tt_assert(buf->first->off == 1);
547 tt_assert(buf->first->buffer == buffer);
548 tt_assert(buf->first->misalign == 0);
549 evbuffer_validate(buf);
552 /* add, expand, pull-up: This used to crash libevent. */
553 buf = evbuffer_new();
555 evbuffer_add(buf, data, sizeof(data));
556 evbuffer_add(buf, data, sizeof(data));
557 evbuffer_add(buf, data, sizeof(data));
559 evbuffer_validate(buf);
560 evbuffer_expand(buf, 1024);
561 evbuffer_validate(buf);
562 evbuffer_pullup(buf, -1);
563 evbuffer_validate(buf);
570 static int reference_cb_called;
572 reference_cb(const void *data, size_t len, void *extra)
574 tt_str_op(data, ==, "this is what we add as read-only memory.");
575 tt_int_op(len, ==, strlen(data));
576 tt_want(extra == (void *)0xdeadaffe);
577 ++reference_cb_called;
583 test_evbuffer_reference(void *ptr)
585 struct evbuffer *src = evbuffer_new();
586 struct evbuffer *dst = evbuffer_new();
587 struct evbuffer_iovec v[1];
588 const char *data = "this is what we add as read-only memory.";
589 reference_cb_called = 0;
591 tt_assert(evbuffer_add_reference(src, data, strlen(data),
592 reference_cb, (void *)0xdeadaffe) != -1);
594 evbuffer_reserve_space(dst, strlen(data), v, 1);
595 tt_assert(evbuffer_remove(src, v[0].iov_base, 10) != -1);
597 evbuffer_validate(src);
598 evbuffer_validate(dst);
600 /* make sure that we don't write data at the beginning */
601 evbuffer_prepend(src, "aaaaa", 5);
602 evbuffer_validate(src);
603 evbuffer_drain(src, 5);
605 tt_assert(evbuffer_remove(src, ((char*)(v[0].iov_base)) + 10,
606 strlen(data) - 10) != -1);
608 v[0].iov_len = strlen(data);
610 evbuffer_commit_space(dst, v, 1);
611 evbuffer_validate(src);
612 evbuffer_validate(dst);
614 tt_int_op(reference_cb_called, ==, 1);
616 tt_assert(!memcmp(evbuffer_pullup(dst, strlen(data)),
617 data, strlen(data)));
618 evbuffer_validate(dst);
625 static struct event_base *addfile_test_event_base = NULL;
626 static int addfile_test_done_writing = 0;
627 static int addfile_test_total_written = 0;
628 static int addfile_test_total_read = 0;
631 addfile_test_writecb(evutil_socket_t fd, short what, void *arg)
633 struct evbuffer *b = arg;
635 evbuffer_validate(b);
636 while (evbuffer_get_length(b)) {
637 r = evbuffer_write(b, fd);
639 addfile_test_total_written += r;
640 TT_BLATHER(("Wrote %d/%d bytes", r, addfile_test_total_written));
642 int e = evutil_socket_geterror(fd);
643 if (EVUTIL_ERR_RW_RETRIABLE(e))
645 tt_fail_perror("write");
646 event_base_loopexit(addfile_test_event_base,NULL);
648 evbuffer_validate(b);
650 addfile_test_done_writing = 1;
653 event_base_loopexit(addfile_test_event_base,NULL);
657 addfile_test_readcb(evutil_socket_t fd, short what, void *arg)
659 struct evbuffer *b = arg;
662 r = evbuffer_read(b, fd, 1024);
664 addfile_test_total_read += r;
665 TT_BLATHER(("Read %d/%d bytes", r, addfile_test_total_read));
669 e = evutil_socket_geterror(fd);
670 if (! EVUTIL_ERR_RW_RETRIABLE(e)) {
671 tt_fail_perror("read");
672 event_base_loopexit(addfile_test_event_base,NULL);
675 if (addfile_test_done_writing &&
676 addfile_test_total_read >= addfile_test_total_written) {
677 event_base_loopexit(addfile_test_event_base,NULL);
682 test_evbuffer_add_file(void *ptr)
684 struct basic_test_data *testdata = ptr;
685 const char *impl = testdata->setup_data;
686 struct evbuffer *src = evbuffer_new(), *dest = evbuffer_new();
687 char *tmpfilename = NULL;
689 const char *expect_data;
690 size_t datalen, expect_len;
693 int want_ismapping = -1, want_cansendfile = -1;
695 int use_segment = 1, use_bigfile = 0, map_from_offset = 0,
696 view_from_offset = 0;
697 struct evbuffer_file_segment *seg = NULL;
698 ev_off_t starting_offset = 0, mapping_len = -1;
699 ev_off_t segment_offset = 0, segment_len = -1;
700 struct event *rev=NULL, *wev=NULL;
701 struct event_base *base = testdata->base;
702 evutil_socket_t pair[2] = {-1, -1};
703 struct evutil_weakrand_state seed = { 123456789U };
705 /* This test is highly parameterized based on substrings of its
706 * argument. The strings are: */
708 if (strstr(impl, "nosegment")) {
709 /* If nosegment is set, use the older evbuffer_add_file
713 if (strstr(impl, "bigfile")) {
714 /* If bigfile is set, use a 512K file. Else use a smaller
718 if (strstr(impl, "map_offset")) {
719 /* If map_offset is set, we build the file segment starting
720 * from a point other than byte 0 and ending somewhere other
721 * than the last byte. Otherwise we map the whole thing */
724 if (strstr(impl, "offset_in_segment")) {
725 /* If offset_in_segment is set, we add a subsection of the
726 * file semgment starting from a point other than byte 0 of
728 view_from_offset = 1;
730 if (strstr(impl, "sendfile")) {
731 /* If sendfile is set, we try to use a sendfile/splice style
733 flags = EVBUF_FS_DISABLE_MMAP;
734 want_cansendfile = 1;
736 } else if (strstr(impl, "mmap")) {
737 /* If sendfile is set, we try to use a mmap/CreateFileMapping
739 flags = EVBUF_FS_DISABLE_SENDFILE;
741 want_cansendfile = 0;
742 } else if (strstr(impl, "linear")) {
743 /* If linear is set, we try to use a read-the-whole-thing
745 flags = EVBUF_FS_DISABLE_SENDFILE|EVBUF_FS_DISABLE_MMAP;
747 want_cansendfile = 0;
748 } else if (strstr(impl, "default")) {
749 /* The caller doesn't care which backend we use. */
752 /* The caller must choose a backend. */
753 TT_DIE(("Didn't recognize the implementation"));
759 data = malloc(1024*512);
761 for (i = 0; i < datalen; ++i)
762 data[i] = (char)evutil_weakrand_(&seed);
764 data = strdup("here is a relatively small string.");
766 datalen = strlen(data);
769 fd = regress_make_tmpfile(data, datalen, &tmpfilename);
771 if (map_from_offset) {
772 starting_offset = datalen/4 + 1;
773 mapping_len = datalen / 2 - 1;
774 expect_data = data + starting_offset;
775 expect_len = mapping_len;
778 expect_len = datalen;
780 if (view_from_offset) {
781 tt_assert(use_segment); /* Can't do this with add_file*/
782 segment_offset = expect_len / 3;
783 segment_len = expect_len / 2;
784 expect_data = expect_data + segment_offset;
785 expect_len = segment_len;
789 seg = evbuffer_file_segment_new(fd, starting_offset,
792 if (want_ismapping >= 0) {
793 if (seg->is_mapping != (unsigned)want_ismapping)
796 if (want_cansendfile >= 0) {
797 if (seg->can_sendfile != (unsigned)want_cansendfile)
802 /* Say that it drains to a fd so that we can use sendfile. */
803 evbuffer_set_flags(src, EVBUFFER_FLAG_DRAINS_TO_FD);
805 #if defined(EVENT__HAVE_SENDFILE) && defined(__sun__) && defined(__svr4__)
806 /* We need to use a pair of AF_INET sockets, since Solaris
807 doesn't support sendfile() over AF_UNIX. */
808 if (evutil_ersatz_socketpair_(AF_INET, SOCK_STREAM, 0, pair) == -1)
809 tt_abort_msg("ersatz_socketpair failed");
811 if (evutil_socketpair(AF_UNIX, SOCK_STREAM, 0, pair) == -1)
812 tt_abort_msg("socketpair failed");
814 evutil_make_socket_nonblocking(pair[0]);
815 evutil_make_socket_nonblocking(pair[1]);
820 tt_assert(evbuffer_add_file_segment(src, seg,
821 segment_offset, segment_len)!=-1);
823 tt_assert(evbuffer_add_file(src, fd, starting_offset,
827 evbuffer_validate(src);
829 addfile_test_event_base = base;
830 wev = event_new(base, pair[0], EV_WRITE|EV_PERSIST,
831 addfile_test_writecb, src);
832 rev = event_new(base, pair[1], EV_READ|EV_PERSIST,
833 addfile_test_readcb, dest);
835 event_add(wev, NULL);
836 event_add(rev, NULL);
837 event_base_dispatch(base);
839 evbuffer_validate(src);
840 evbuffer_validate(dest);
842 tt_assert(addfile_test_done_writing);
843 tt_int_op(addfile_test_total_written, ==, expect_len);
844 tt_int_op(addfile_test_total_read, ==, expect_len);
846 compare = (char *)evbuffer_pullup(dest, expect_len);
847 tt_assert(compare != NULL);
848 if (memcmp(compare, expect_data, expect_len)) {
849 tt_abort_msg("Data from add_file differs.");
852 evbuffer_validate(dest);
857 evbuffer_file_segment_free(seg);
863 evutil_closesocket(pair[0]);
865 evutil_closesocket(pair[1]);
876 static int file_segment_cleanup_cb_called_count = 0;
877 static struct evbuffer_file_segment const* file_segment_cleanup_cb_called_with = NULL;
878 static int file_segment_cleanup_cb_called_with_flags = 0;
879 static void* file_segment_cleanup_cb_called_with_arg = NULL;
881 file_segment_cleanup_cp(struct evbuffer_file_segment const* seg, int flags, void* arg)
883 ++file_segment_cleanup_cb_called_count;
884 file_segment_cleanup_cb_called_with = seg;
885 file_segment_cleanup_cb_called_with_flags = flags;
886 file_segment_cleanup_cb_called_with_arg = arg;
890 test_evbuffer_file_segment_add_cleanup_cb(void* ptr)
892 char *tmpfilename = NULL;
894 struct evbuffer *evb = NULL;
895 struct evbuffer_file_segment *seg = NULL, *segptr;
896 char const* arg = "token";
898 fd = regress_make_tmpfile("file_segment_test_file", 22, &tmpfilename);
899 tt_int_op(fd, >=, 0);
901 evb = evbuffer_new();
904 segptr = seg = evbuffer_file_segment_new(fd, 0, -1, 0);
907 evbuffer_file_segment_add_cleanup_cb(
908 seg, &file_segment_cleanup_cp, (void*)arg);
912 tt_assert(evbuffer_add_file_segment(evb, seg, 0, -1)!=-1);
914 evbuffer_validate(evb);
916 tt_int_op(file_segment_cleanup_cb_called_count, ==, 0);
917 evbuffer_file_segment_free(seg);
918 seg = NULL; /* Prevent double-free. */
920 tt_int_op(file_segment_cleanup_cb_called_count, ==, 0);
922 evb = NULL; /* pevent double-free */
924 tt_int_op(file_segment_cleanup_cb_called_count, ==, 1);
925 tt_assert(file_segment_cleanup_cb_called_with == segptr);
926 tt_assert(file_segment_cleanup_cb_called_with_flags == 0);
927 tt_assert(file_segment_cleanup_cb_called_with_arg == (void*)arg);
933 evbuffer_file_segment_free(seg);
940 #ifndef EVENT__DISABLE_MM_REPLACEMENT
942 failing_malloc(size_t how_much)
950 test_evbuffer_readln(void *ptr)
952 struct evbuffer *evb = evbuffer_new();
953 struct evbuffer *evb_tmp = evbuffer_new();
958 #define tt_line_eq(content) \
960 if (!cp || sz != strlen(content) || strcmp(cp, content)) { \
961 TT_DIE(("Wanted %s; got %s [%d]", content, cp, (int)sz)); \
966 s = "complex silly newline\r\n\n\r\n\n\rmore\0\n";
967 evbuffer_add(evb, s, strlen(s)+2);
968 evbuffer_validate(evb);
969 cp = evbuffer_readln(evb, &sz, EVBUFFER_EOL_ANY);
970 tt_line_eq("complex silly newline");
972 evbuffer_validate(evb);
973 cp = evbuffer_readln(evb, &sz, EVBUFFER_EOL_ANY);
974 if (!cp || sz != 5 || memcmp(cp, "more\0\0", 6))
975 tt_abort_msg("Not as expected");
976 tt_uint_op(evbuffer_get_length(evb), ==, 0);
977 evbuffer_validate(evb);
979 evbuffer_add(evb, s, strlen(s));
981 evbuffer_validate(evb);
982 cp = evbuffer_readln(evb, &sz, EVBUFFER_EOL_ANY);
985 evbuffer_validate(evb);
986 cp = evbuffer_readln(evb, &sz, EVBUFFER_EOL_ANY);
988 evbuffer_validate(evb);
989 evbuffer_drain(evb, evbuffer_get_length(evb));
990 tt_assert(evbuffer_get_length(evb) == 0);
991 evbuffer_validate(evb);
994 s = "Line with\rin the middle\nLine with good crlf\r\n\nfinal\n";
995 evbuffer_add(evb, s, strlen(s));
996 evbuffer_validate(evb);
997 cp = evbuffer_readln(evb, &sz, EVBUFFER_EOL_CRLF);
998 tt_line_eq("Line with\rin the middle");
1000 evbuffer_validate(evb);
1002 cp = evbuffer_readln(evb, &sz, EVBUFFER_EOL_CRLF);
1003 tt_line_eq("Line with good crlf");
1005 evbuffer_validate(evb);
1007 cp = evbuffer_readln(evb, &sz, EVBUFFER_EOL_CRLF);
1010 evbuffer_validate(evb);
1012 cp = evbuffer_readln(evb, &sz, EVBUFFER_EOL_CRLF);
1013 tt_line_eq("final");
1015 evbuffer_validate(evb);
1016 evbuffer_add(evb, s, 1);
1017 evbuffer_validate(evb);
1019 cp = evbuffer_readln(evb, &sz, EVBUFFER_EOL_CRLF);
1021 evbuffer_validate(evb);
1023 /* Test CRLF_STRICT */
1024 s = " and a bad crlf\nand a good one\r\n\r\nMore\r";
1025 evbuffer_add(evb, s, strlen(s));
1026 evbuffer_validate(evb);
1027 cp = evbuffer_readln(evb, &sz, EVBUFFER_EOL_CRLF_STRICT);
1028 tt_line_eq("x and a bad crlf\nand a good one");
1030 evbuffer_validate(evb);
1032 cp = evbuffer_readln(evb, &sz, EVBUFFER_EOL_CRLF_STRICT);
1035 evbuffer_validate(evb);
1037 cp = evbuffer_readln(evb, &sz, EVBUFFER_EOL_CRLF_STRICT);
1039 evbuffer_validate(evb);
1040 evbuffer_add(evb, "\n", 1);
1041 evbuffer_validate(evb);
1043 cp = evbuffer_readln(evb, &sz, EVBUFFER_EOL_CRLF_STRICT);
1046 tt_assert(evbuffer_get_length(evb) == 0);
1047 evbuffer_validate(evb);
1049 s = "An internal CR\r is not an eol\r\nNor is a lack of one";
1050 evbuffer_add(evb, s, strlen(s));
1051 cp = evbuffer_readln(evb, &sz, EVBUFFER_EOL_CRLF_STRICT);
1052 tt_line_eq("An internal CR\r is not an eol");
1054 evbuffer_validate(evb);
1056 cp = evbuffer_readln(evb, &sz, EVBUFFER_EOL_CRLF_STRICT);
1058 evbuffer_validate(evb);
1060 evbuffer_add(evb, "\r\n", 2);
1061 evbuffer_validate(evb);
1062 cp = evbuffer_readln(evb, &sz, EVBUFFER_EOL_CRLF_STRICT);
1063 tt_line_eq("Nor is a lack of one");
1065 tt_assert(evbuffer_get_length(evb) == 0);
1066 evbuffer_validate(evb);
1069 s = "An\rand a nl\n\nText";
1070 evbuffer_add(evb, s, strlen(s));
1071 evbuffer_validate(evb);
1073 cp = evbuffer_readln(evb, &sz, EVBUFFER_EOL_LF);
1074 tt_line_eq("An\rand a nl");
1076 evbuffer_validate(evb);
1078 cp = evbuffer_readln(evb, &sz, EVBUFFER_EOL_LF);
1081 evbuffer_validate(evb);
1083 cp = evbuffer_readln(evb, &sz, EVBUFFER_EOL_LF);
1086 evbuffer_add(evb, "\n", 1);
1087 evbuffer_validate(evb);
1088 cp = evbuffer_readln(evb, &sz, EVBUFFER_EOL_LF);
1091 evbuffer_validate(evb);
1094 tt_int_op(evbuffer_get_length(evb), ==, 0);
1098 "The all-zeros character which may serve\0"
1099 "to accomplish time fill\0and media fill";
1100 /* Add all but the final NUL of x. */
1101 evbuffer_add(evb, x, sizeof(x)-1);
1103 cp = evbuffer_readln(evb, &sz, EVBUFFER_EOL_NUL);
1104 tt_line_eq("NUL\n");
1106 cp = evbuffer_readln(evb, &sz, EVBUFFER_EOL_NUL);
1109 cp = evbuffer_readln(evb, &sz, EVBUFFER_EOL_NUL);
1110 tt_line_eq("The all-zeros character which may serve");
1112 cp = evbuffer_readln(evb, &sz, EVBUFFER_EOL_NUL);
1113 tt_line_eq("to accomplish time fill");
1115 cp = evbuffer_readln(evb, &sz, EVBUFFER_EOL_NUL);
1116 tt_ptr_op(cp, ==, NULL);
1117 evbuffer_drain(evb, -1);
1119 /* Test CRLF_STRICT - across boundaries*/
1120 s = " and a bad crlf\nand a good one\r";
1121 evbuffer_add(evb_tmp, s, strlen(s));
1122 evbuffer_validate(evb);
1123 evbuffer_add_buffer(evb, evb_tmp);
1124 evbuffer_validate(evb);
1126 evbuffer_add(evb_tmp, s, strlen(s));
1127 evbuffer_validate(evb);
1128 evbuffer_add_buffer(evb, evb_tmp);
1129 evbuffer_validate(evb);
1131 evbuffer_add(evb_tmp, s, strlen(s));
1132 evbuffer_validate(evb);
1133 evbuffer_add_buffer(evb, evb_tmp);
1134 evbuffer_validate(evb);
1136 cp = evbuffer_readln(evb, &sz, EVBUFFER_EOL_CRLF_STRICT);
1137 tt_line_eq(" and a bad crlf\nand a good one");
1139 evbuffer_validate(evb);
1141 cp = evbuffer_readln(evb, &sz, EVBUFFER_EOL_CRLF_STRICT);
1144 evbuffer_validate(evb);
1146 cp = evbuffer_readln(evb, &sz, EVBUFFER_EOL_CRLF_STRICT);
1149 evbuffer_validate(evb);
1150 evbuffer_add(evb, "\n", 1);
1151 evbuffer_validate(evb);
1152 cp = evbuffer_readln(evb, &sz, EVBUFFER_EOL_CRLF_STRICT);
1154 free(cp); cp = NULL;
1155 evbuffer_validate(evb);
1156 tt_assert(evbuffer_get_length(evb) == 0);
1158 /* Test memory problem*/
1159 s = "one line\ntwo line\nblue line";
1160 evbuffer_add(evb_tmp, s, strlen(s));
1161 evbuffer_validate(evb);
1162 evbuffer_add_buffer(evb, evb_tmp);
1163 evbuffer_validate(evb);
1165 cp = evbuffer_readln(evb, &sz, EVBUFFER_EOL_LF);
1166 tt_line_eq("one line");
1167 free(cp); cp = NULL;
1168 evbuffer_validate(evb);
1170 /* the next call to readline should fail */
1171 #ifndef EVENT__DISABLE_MM_REPLACEMENT
1172 event_set_mem_functions(failing_malloc, realloc, free);
1173 cp = evbuffer_readln(evb, &sz, EVBUFFER_EOL_LF);
1174 tt_assert(cp == NULL);
1175 evbuffer_validate(evb);
1177 /* now we should get the next line back */
1178 event_set_mem_functions(malloc, realloc, free);
1180 cp = evbuffer_readln(evb, &sz, EVBUFFER_EOL_LF);
1181 tt_line_eq("two line");
1182 free(cp); cp = NULL;
1183 evbuffer_validate(evb);
1187 evbuffer_free(evb_tmp);
1192 test_evbuffer_search_eol(void *ptr)
1194 struct evbuffer *buf = evbuffer_new();
1195 struct evbuffer_ptr ptr1, ptr2;
1199 s = "string! \r\n\r\nx\n";
1200 evbuffer_add(buf, s, strlen(s));
1202 ptr1 = evbuffer_search_eol(buf, NULL, &eol_len, EVBUFFER_EOL_CRLF);
1203 tt_int_op(ptr1.pos, ==, 8);
1204 tt_int_op(eol_len, ==, 2);
1207 ptr2 = evbuffer_search_eol(buf, &ptr1, &eol_len, EVBUFFER_EOL_CRLF);
1208 tt_int_op(ptr2.pos, ==, 8);
1209 tt_int_op(eol_len, ==, 2);
1211 evbuffer_ptr_set(buf, &ptr1, 1, EVBUFFER_PTR_ADD);
1213 ptr2 = evbuffer_search_eol(buf, &ptr1, &eol_len, EVBUFFER_EOL_CRLF);
1214 tt_int_op(ptr2.pos, ==, 9);
1215 tt_int_op(eol_len, ==, 1);
1218 ptr2 = evbuffer_search_eol(buf, &ptr1, &eol_len, EVBUFFER_EOL_CRLF_STRICT);
1219 tt_int_op(ptr2.pos, ==, 10);
1220 tt_int_op(eol_len, ==, 2);
1223 ptr1 = evbuffer_search_eol(buf, NULL, &eol_len, EVBUFFER_EOL_LF);
1224 tt_int_op(ptr1.pos, ==, 9);
1225 tt_int_op(eol_len, ==, 1);
1228 ptr2 = evbuffer_search_eol(buf, &ptr1, &eol_len, EVBUFFER_EOL_LF);
1229 tt_int_op(ptr2.pos, ==, 9);
1230 tt_int_op(eol_len, ==, 1);
1232 evbuffer_ptr_set(buf, &ptr1, 1, EVBUFFER_PTR_ADD);
1234 ptr2 = evbuffer_search_eol(buf, &ptr1, &eol_len, EVBUFFER_EOL_LF);
1235 tt_int_op(ptr2.pos, ==, 11);
1236 tt_int_op(eol_len, ==, 1);
1238 tt_assert(evbuffer_ptr_set(buf, &ptr1, evbuffer_get_length(buf), EVBUFFER_PTR_SET) == 0);
1240 ptr2 = evbuffer_search_eol(buf, &ptr1, &eol_len, EVBUFFER_EOL_LF);
1241 tt_int_op(ptr2.pos, ==, -1);
1242 tt_int_op(eol_len, ==, 0);
1249 test_evbuffer_iterative(void *ptr)
1251 struct evbuffer *buf = evbuffer_new();
1252 const char *abc = "abcdefghijklmnopqrstvuwxyzabcdefghijklmnopqrstvuwxyzabcdefghijklmnopqrstvuwxyzabcdefghijklmnopqrstvuwxyz";
1253 unsigned i, j, sum, n;
1257 for (i = 0; i < 1000; ++i) {
1258 for (j = 1; j < strlen(abc); ++j) {
1260 evutil_snprintf(format, sizeof(format), "%%%u.%us", j, j);
1261 evbuffer_add_printf(buf, format, abc);
1263 /* Only check for rep violations every so often.
1264 Walking over the whole list of chains can get
1265 pretty expensive as it gets long.
1268 evbuffer_validate(buf);
1274 evbuffer_validate(buf);
1276 tt_uint_op(sum, ==, evbuffer_get_length(buf));
1281 evbuffer_get_waste(buf, &a, &w, &u);
1283 printf("Allocated: %u.\nWasted: %u.\nUsed: %u.",
1284 (unsigned)a, (unsigned)w, (unsigned)u);
1285 tt_assert( ((double)w)/a < .125);
1293 test_evbuffer_find(void *ptr)
1296 const char* test1 = "1234567890\r\n";
1297 const char* test2 = "1234567890\r";
1298 #define EVBUFFER_INITIAL_LENGTH 256
1299 char test3[EVBUFFER_INITIAL_LENGTH];
1301 struct evbuffer * buf = evbuffer_new();
1305 /* make sure evbuffer_find doesn't match past the end of the buffer */
1306 evbuffer_add(buf, (u_char*)test1, strlen(test1));
1307 evbuffer_validate(buf);
1308 evbuffer_drain(buf, strlen(test1));
1309 evbuffer_validate(buf);
1310 evbuffer_add(buf, (u_char*)test2, strlen(test2));
1311 evbuffer_validate(buf);
1312 p = evbuffer_find(buf, (u_char*)"\r\n", 2);
1316 * drain the buffer and do another find; in r309 this would
1317 * read past the allocated buffer causing a valgrind error.
1319 evbuffer_drain(buf, strlen(test2));
1320 evbuffer_validate(buf);
1321 for (i = 0; i < EVBUFFER_INITIAL_LENGTH; ++i)
1323 test3[EVBUFFER_INITIAL_LENGTH - 1] = 'x';
1324 evbuffer_add(buf, (u_char *)test3, EVBUFFER_INITIAL_LENGTH);
1325 evbuffer_validate(buf);
1326 p = evbuffer_find(buf, (u_char *)"xy", 2);
1329 /* simple test for match at end of allocated buffer */
1330 p = evbuffer_find(buf, (u_char *)"ax", 2);
1331 tt_assert(p != NULL);
1332 tt_want(strncmp((char*)p, "ax", 2) == 0);
1340 test_evbuffer_ptr_set(void *ptr)
1342 struct evbuffer *buf = evbuffer_new();
1343 struct evbuffer_ptr pos;
1344 struct evbuffer_iovec v[1];
1348 tt_int_op(evbuffer_get_length(buf), ==, 0);
1350 tt_assert(evbuffer_ptr_set(buf, &pos, 0, EVBUFFER_PTR_SET) == 0);
1351 tt_assert(pos.pos == 0);
1352 tt_assert(evbuffer_ptr_set(buf, &pos, 1, EVBUFFER_PTR_ADD) == -1);
1353 tt_assert(pos.pos == -1);
1354 tt_assert(evbuffer_ptr_set(buf, &pos, 1, EVBUFFER_PTR_SET) == -1);
1355 tt_assert(pos.pos == -1);
1357 /* create some chains */
1358 evbuffer_reserve_space(buf, 5000, v, 1);
1359 v[0].iov_len = 5000;
1360 memset(v[0].iov_base, 1, v[0].iov_len);
1361 evbuffer_commit_space(buf, v, 1);
1362 evbuffer_validate(buf);
1364 evbuffer_reserve_space(buf, 4000, v, 1);
1365 v[0].iov_len = 4000;
1366 memset(v[0].iov_base, 2, v[0].iov_len);
1367 evbuffer_commit_space(buf, v, 1);
1369 evbuffer_reserve_space(buf, 3000, v, 1);
1370 v[0].iov_len = 3000;
1371 memset(v[0].iov_base, 3, v[0].iov_len);
1372 evbuffer_commit_space(buf, v, 1);
1373 evbuffer_validate(buf);
1375 tt_int_op(evbuffer_get_length(buf), ==, 12000);
1377 tt_assert(evbuffer_ptr_set(buf, &pos, 13000, EVBUFFER_PTR_SET) == -1);
1378 tt_assert(pos.pos == -1);
1379 tt_assert(evbuffer_ptr_set(buf, &pos, 0, EVBUFFER_PTR_SET) == 0);
1380 tt_assert(pos.pos == 0);
1381 tt_assert(evbuffer_ptr_set(buf, &pos, 13000, EVBUFFER_PTR_ADD) == -1);
1383 tt_assert(evbuffer_ptr_set(buf, &pos, 0, EVBUFFER_PTR_SET) == 0);
1384 tt_assert(pos.pos == 0);
1385 tt_assert(evbuffer_ptr_set(buf, &pos, 10000, EVBUFFER_PTR_ADD) == 0);
1386 tt_assert(pos.pos == 10000);
1387 tt_assert(evbuffer_ptr_set(buf, &pos, 1000, EVBUFFER_PTR_ADD) == 0);
1388 tt_assert(pos.pos == 11000);
1389 tt_assert(evbuffer_ptr_set(buf, &pos, 1000, EVBUFFER_PTR_ADD) == 0);
1390 tt_assert(pos.pos == 12000);
1391 tt_assert(evbuffer_ptr_set(buf, &pos, 1000, EVBUFFER_PTR_ADD) == -1);
1392 tt_assert(pos.pos == -1);
1400 test_evbuffer_search(void *ptr)
1402 struct evbuffer *buf = evbuffer_new();
1403 struct evbuffer *tmp = evbuffer_new();
1404 struct evbuffer_ptr pos, end;
1409 pos = evbuffer_search(buf, "x", 1, NULL);
1410 tt_int_op(pos.pos, ==, -1);
1411 tt_assert(evbuffer_ptr_set(buf, &pos, 0, EVBUFFER_PTR_SET) == 0);
1412 pos = evbuffer_search(buf, "x", 1, &pos);
1413 tt_int_op(pos.pos, ==, -1);
1414 tt_assert(evbuffer_ptr_set(buf, &pos, 0, EVBUFFER_PTR_SET) == 0);
1415 pos = evbuffer_search_range(buf, "x", 1, &pos, &pos);
1416 tt_int_op(pos.pos, ==, -1);
1417 tt_assert(evbuffer_ptr_set(buf, &pos, 0, EVBUFFER_PTR_SET) == 0);
1418 pos = evbuffer_search_range(buf, "x", 1, &pos, NULL);
1419 tt_int_op(pos.pos, ==, -1);
1421 /* set up our chains */
1422 evbuffer_add_printf(tmp, "hello"); /* 5 chars */
1423 evbuffer_add_buffer(buf, tmp);
1424 evbuffer_add_printf(tmp, "foo"); /* 3 chars */
1425 evbuffer_add_buffer(buf, tmp);
1426 evbuffer_add_printf(tmp, "cat"); /* 3 chars */
1427 evbuffer_add_buffer(buf, tmp);
1428 evbuffer_add_printf(tmp, "attack");
1429 evbuffer_add_buffer(buf, tmp);
1431 pos = evbuffer_search(buf, "attack", 6, NULL);
1432 tt_int_op(pos.pos, ==, 11);
1433 pos = evbuffer_search(buf, "attacker", 8, NULL);
1434 tt_int_op(pos.pos, ==, -1);
1436 /* test continuing search */
1437 pos = evbuffer_search(buf, "oc", 2, NULL);
1438 tt_int_op(pos.pos, ==, 7);
1439 pos = evbuffer_search(buf, "cat", 3, &pos);
1440 tt_int_op(pos.pos, ==, 8);
1441 pos = evbuffer_search(buf, "tacking", 7, &pos);
1442 tt_int_op(pos.pos, ==, -1);
1444 evbuffer_ptr_set(buf, &pos, 5, EVBUFFER_PTR_SET);
1445 pos = evbuffer_search(buf, "foo", 3, &pos);
1446 tt_int_op(pos.pos, ==, 5);
1448 evbuffer_ptr_set(buf, &pos, 2, EVBUFFER_PTR_ADD);
1449 pos = evbuffer_search(buf, "tat", 3, &pos);
1450 tt_int_op(pos.pos, ==, 10);
1452 /* test bounded search. */
1453 /* Set "end" to the first t in "attack". */
1454 evbuffer_ptr_set(buf, &end, 12, EVBUFFER_PTR_SET);
1455 pos = evbuffer_search_range(buf, "foo", 3, NULL, &end);
1456 tt_int_op(pos.pos, ==, 5);
1457 pos = evbuffer_search_range(buf, "foocata", 7, NULL, &end);
1458 tt_int_op(pos.pos, ==, 5);
1459 pos = evbuffer_search_range(buf, "foocatat", 8, NULL, &end);
1460 tt_int_op(pos.pos, ==, -1);
1461 pos = evbuffer_search_range(buf, "ack", 3, NULL, &end);
1462 tt_int_op(pos.pos, ==, -1);
1464 /* Set "end" after the last byte in the buffer. */
1465 tt_assert(evbuffer_ptr_set(buf, &end, 17, EVBUFFER_PTR_SET) == 0);
1467 pos = evbuffer_search_range(buf, "attack", 6, NULL, &end);
1468 tt_int_op(pos.pos, ==, 11);
1469 tt_assert(evbuffer_ptr_set(buf, &pos, 11, EVBUFFER_PTR_SET) == 0);
1470 pos = evbuffer_search_range(buf, "attack", 6, &pos, &end);
1471 tt_int_op(pos.pos, ==, 11);
1472 tt_assert(evbuffer_ptr_set(buf, &pos, 17, EVBUFFER_PTR_SET) == 0);
1473 pos = evbuffer_search_range(buf, "attack", 6, &pos, &end);
1474 tt_int_op(pos.pos, ==, -1);
1475 tt_assert(evbuffer_ptr_set(buf, &pos, 17, EVBUFFER_PTR_SET) == 0);
1476 pos = evbuffer_search_range(buf, "attack", 6, &pos, NULL);
1477 tt_int_op(pos.pos, ==, -1);
1487 log_change_callback(struct evbuffer *buffer,
1488 const struct evbuffer_cb_info *cbinfo,
1492 size_t old_len = cbinfo->orig_size;
1493 size_t new_len = old_len + cbinfo->n_added - cbinfo->n_deleted;
1494 struct evbuffer *out = arg;
1495 evbuffer_add_printf(out, "%lu->%lu; ", (unsigned long)old_len,
1496 (unsigned long)new_len);
1499 self_draining_callback(struct evbuffer *evbuffer, size_t old_len,
1500 size_t new_len, void *arg)
1502 if (new_len > old_len)
1503 evbuffer_drain(evbuffer, new_len);
1507 test_evbuffer_callbacks(void *ptr)
1509 struct evbuffer *buf = evbuffer_new();
1510 struct evbuffer *buf_out1 = evbuffer_new();
1511 struct evbuffer *buf_out2 = evbuffer_new();
1512 struct evbuffer_cb_entry *cb1, *cb2;
1515 tt_assert(buf_out1);
1516 tt_assert(buf_out2);
1518 cb1 = evbuffer_add_cb(buf, log_change_callback, buf_out1);
1519 cb2 = evbuffer_add_cb(buf, log_change_callback, buf_out2);
1521 /* Let's run through adding and deleting some stuff from the buffer
1522 * and turning the callbacks on and off and removing them. The callback
1523 * adds a summary of length changes to buf_out1/buf_out2 when called. */
1525 evbuffer_add_printf(buf, "The %d magic words are spotty pudding", 2);
1526 evbuffer_validate(buf);
1527 evbuffer_cb_clear_flags(buf, cb2, EVBUFFER_CB_ENABLED);
1528 evbuffer_drain(buf, 10); /*36->26*/
1529 evbuffer_validate(buf);
1530 evbuffer_prepend(buf, "Hello", 5);/*26->31*/
1531 evbuffer_cb_set_flags(buf, cb2, EVBUFFER_CB_ENABLED);
1532 evbuffer_add_reference(buf, "Goodbye", 7, NULL, NULL); /*31->38*/
1533 evbuffer_remove_cb_entry(buf, cb1);
1534 evbuffer_validate(buf);
1535 evbuffer_drain(buf, evbuffer_get_length(buf)); /*38->0*/;
1536 tt_assert(-1 == evbuffer_remove_cb(buf, log_change_callback, NULL));
1537 evbuffer_add(buf, "X", 1); /* 0->1 */
1538 tt_assert(!evbuffer_remove_cb(buf, log_change_callback, buf_out2));
1539 evbuffer_validate(buf);
1541 tt_str_op((const char *) evbuffer_pullup(buf_out1, -1), ==,
1542 "0->36; 36->26; 26->31; 31->38; ");
1543 tt_str_op((const char *) evbuffer_pullup(buf_out2, -1), ==,
1544 "0->36; 31->38; 38->0; 0->1; ");
1545 evbuffer_drain(buf_out1, evbuffer_get_length(buf_out1));
1546 evbuffer_drain(buf_out2, evbuffer_get_length(buf_out2));
1547 /* Let's test the obsolete buffer_setcb function too. */
1548 cb1 = evbuffer_add_cb(buf, log_change_callback, buf_out1);
1549 tt_assert(cb1 != NULL);
1550 cb2 = evbuffer_add_cb(buf, log_change_callback, buf_out2);
1551 tt_assert(cb2 != NULL);
1552 evbuffer_setcb(buf, self_draining_callback, NULL);
1553 evbuffer_add_printf(buf, "This should get drained right away.");
1554 tt_uint_op(evbuffer_get_length(buf), ==, 0);
1555 tt_uint_op(evbuffer_get_length(buf_out1), ==, 0);
1556 tt_uint_op(evbuffer_get_length(buf_out2), ==, 0);
1557 evbuffer_setcb(buf, NULL, NULL);
1558 evbuffer_add_printf(buf, "This will not.");
1559 tt_str_op((const char *) evbuffer_pullup(buf, -1), ==, "This will not.");
1560 evbuffer_validate(buf);
1561 evbuffer_drain(buf, evbuffer_get_length(buf));
1562 evbuffer_validate(buf);
1564 /* Now let's try a suspended callback. */
1565 cb1 = evbuffer_add_cb(buf, log_change_callback, buf_out1);
1566 cb2 = evbuffer_add_cb(buf, log_change_callback, buf_out2);
1567 evbuffer_cb_suspend(buf,cb2);
1568 evbuffer_prepend(buf,"Hello world",11); /*0->11*/
1569 evbuffer_validate(buf);
1570 evbuffer_cb_suspend(buf,cb1);
1571 evbuffer_add(buf,"more",4); /* 11->15 */
1572 evbuffer_cb_unsuspend(buf,cb2);
1573 evbuffer_drain(buf, 4); /* 15->11 */
1574 evbuffer_cb_unsuspend(buf,cb1);
1575 evbuffer_drain(buf, evbuffer_get_length(buf)); /* 11->0 */
1577 tt_str_op(evbuffer_pullup(buf_out1, -1), ==,
1578 "0->11; 11->11; 11->0; ");
1579 tt_str_op(evbuffer_pullup(buf_out2, -1), ==,
1580 "0->15; 15->11; 11->0; ");
1587 evbuffer_free(buf_out1);
1589 evbuffer_free(buf_out2);
1592 static int ref_done_cb_called_count = 0;
1593 static void *ref_done_cb_called_with = NULL;
1594 static const void *ref_done_cb_called_with_data = NULL;
1595 static size_t ref_done_cb_called_with_len = 0;
1596 static void ref_done_cb(const void *data, size_t len, void *info)
1598 ++ref_done_cb_called_count;
1599 ref_done_cb_called_with = info;
1600 ref_done_cb_called_with_data = data;
1601 ref_done_cb_called_with_len = len;
1605 test_evbuffer_add_reference(void *ptr)
1607 const char chunk1[] = "If you have found the answer to such a problem";
1608 const char chunk2[] = "you ought to write it up for publication";
1609 /* -- Knuth's "Notes on the Exercises" from TAOCP */
1611 size_t len1 = strlen(chunk1), len2=strlen(chunk2);
1613 struct evbuffer *buf1 = NULL, *buf2 = NULL;
1615 buf1 = evbuffer_new();
1618 evbuffer_add_reference(buf1, chunk1, len1, ref_done_cb, (void*)111);
1619 evbuffer_add(buf1, ", ", 2);
1620 evbuffer_add_reference(buf1, chunk2, len2, ref_done_cb, (void*)222);
1621 tt_int_op(evbuffer_get_length(buf1), ==, len1+len2+2);
1623 /* Make sure we can drain a little from a reference. */
1624 tt_int_op(evbuffer_remove(buf1, tmp, 6), ==, 6);
1625 tt_int_op(memcmp(tmp, "If you", 6), ==, 0);
1626 tt_int_op(evbuffer_remove(buf1, tmp, 5), ==, 5);
1627 tt_int_op(memcmp(tmp, " have", 5), ==, 0);
1629 /* Make sure that prepending does not meddle with immutable data */
1630 tt_int_op(evbuffer_prepend(buf1, "I have ", 7), ==, 0);
1631 tt_int_op(memcmp(chunk1, "If you", 6), ==, 0);
1632 evbuffer_validate(buf1);
1634 /* Make sure that when the chunk is over, the callback is invoked. */
1635 evbuffer_drain(buf1, 7); /* Remove prepended stuff. */
1636 evbuffer_drain(buf1, len1-11-1); /* remove all but one byte of chunk1 */
1637 tt_int_op(ref_done_cb_called_count, ==, 0);
1638 evbuffer_remove(buf1, tmp, 1);
1639 tt_int_op(tmp[0], ==, 'm');
1640 tt_assert(ref_done_cb_called_with == (void*)111);
1641 tt_assert(ref_done_cb_called_with_data == chunk1);
1642 tt_assert(ref_done_cb_called_with_len == len1);
1643 tt_int_op(ref_done_cb_called_count, ==, 1);
1644 evbuffer_validate(buf1);
1646 /* Drain some of the remaining chunk, then add it to another buffer */
1647 evbuffer_drain(buf1, 6); /* Remove the ", you ". */
1648 buf2 = evbuffer_new();
1650 tt_int_op(ref_done_cb_called_count, ==, 1);
1651 evbuffer_add(buf2, "I ", 2);
1653 evbuffer_add_buffer(buf2, buf1);
1654 tt_int_op(ref_done_cb_called_count, ==, 1);
1655 evbuffer_remove(buf2, tmp, 16);
1656 tt_int_op(memcmp("I ought to write", tmp, 16), ==, 0);
1657 evbuffer_drain(buf2, evbuffer_get_length(buf2));
1658 tt_int_op(ref_done_cb_called_count, ==, 2);
1659 tt_assert(ref_done_cb_called_with == (void*)222);
1660 evbuffer_validate(buf2);
1662 /* Now add more stuff to buf1 and make sure that it gets removed on
1664 evbuffer_add(buf1, "You shake and shake the ", 24);
1665 evbuffer_add_reference(buf1, "ketchup bottle", 14, ref_done_cb,
1667 evbuffer_add(buf1, ". Nothing comes and then a lot'll.", 35);
1668 evbuffer_free(buf1);
1670 tt_int_op(ref_done_cb_called_count, ==, 3);
1671 tt_assert(ref_done_cb_called_with == (void*)3333);
1675 evbuffer_free(buf1);
1677 evbuffer_free(buf2);
1681 test_evbuffer_multicast(void *ptr)
1683 const char chunk1[] = "If you have found the answer to such a problem";
1684 const char chunk2[] = "you ought to write it up for publication";
1685 /* -- Knuth's "Notes on the Exercises" from TAOCP */
1687 size_t len1 = strlen(chunk1), len2=strlen(chunk2);
1689 struct evbuffer *buf1 = NULL, *buf2 = NULL;
1691 buf1 = evbuffer_new();
1694 evbuffer_add(buf1, chunk1, len1);
1695 evbuffer_add(buf1, ", ", 2);
1696 evbuffer_add(buf1, chunk2, len2);
1697 tt_int_op(evbuffer_get_length(buf1), ==, len1+len2+2);
1699 buf2 = evbuffer_new();
1702 tt_int_op(evbuffer_add_buffer_reference(buf2, buf1), ==, 0);
1703 /* nested references are not allowed */
1704 tt_int_op(evbuffer_add_buffer_reference(buf2, buf2), ==, -1);
1705 tt_int_op(evbuffer_add_buffer_reference(buf1, buf2), ==, -1);
1707 /* both buffers contain the same amount of data */
1708 tt_int_op(evbuffer_get_length(buf1), ==, evbuffer_get_length(buf1));
1710 /* Make sure we can drain a little from the first buffer. */
1711 tt_int_op(evbuffer_remove(buf1, tmp, 6), ==, 6);
1712 tt_int_op(memcmp(tmp, "If you", 6), ==, 0);
1713 tt_int_op(evbuffer_remove(buf1, tmp, 5), ==, 5);
1714 tt_int_op(memcmp(tmp, " have", 5), ==, 0);
1716 /* Make sure that prepending does not meddle with immutable data */
1717 tt_int_op(evbuffer_prepend(buf1, "I have ", 7), ==, 0);
1718 tt_int_op(memcmp(chunk1, "If you", 6), ==, 0);
1719 evbuffer_validate(buf1);
1721 /* Make sure we can drain a little from the second buffer. */
1722 tt_int_op(evbuffer_remove(buf2, tmp, 6), ==, 6);
1723 tt_int_op(memcmp(tmp, "If you", 6), ==, 0);
1724 tt_int_op(evbuffer_remove(buf2, tmp, 5), ==, 5);
1725 tt_int_op(memcmp(tmp, " have", 5), ==, 0);
1727 /* Make sure that prepending does not meddle with immutable data */
1728 tt_int_op(evbuffer_prepend(buf2, "I have ", 7), ==, 0);
1729 tt_int_op(memcmp(chunk1, "If you", 6), ==, 0);
1730 evbuffer_validate(buf2);
1732 /* Make sure the data can be read from the second buffer when the first is freed */
1733 evbuffer_free(buf1);
1736 tt_int_op(evbuffer_remove(buf2, tmp, 6), ==, 6);
1737 tt_int_op(memcmp(tmp, "I have", 6), ==, 0);
1739 tt_int_op(evbuffer_remove(buf2, tmp, 6), ==, 6);
1740 tt_int_op(memcmp(tmp, " foun", 6), ==, 0);
1744 evbuffer_free(buf1);
1746 evbuffer_free(buf2);
1750 test_evbuffer_multicast_drain(void *ptr)
1752 const char chunk1[] = "If you have found the answer to such a problem";
1753 const char chunk2[] = "you ought to write it up for publication";
1754 /* -- Knuth's "Notes on the Exercises" from TAOCP */
1755 size_t len1 = strlen(chunk1), len2=strlen(chunk2);
1757 struct evbuffer *buf1 = NULL, *buf2 = NULL;
1759 buf1 = evbuffer_new();
1762 evbuffer_add(buf1, chunk1, len1);
1763 evbuffer_add(buf1, ", ", 2);
1764 evbuffer_add(buf1, chunk2, len2);
1765 tt_int_op(evbuffer_get_length(buf1), ==, len1+len2+2);
1767 buf2 = evbuffer_new();
1770 tt_int_op(evbuffer_add_buffer_reference(buf2, buf1), ==, 0);
1771 tt_int_op(evbuffer_get_length(buf2), ==, len1+len2+2);
1772 tt_int_op(evbuffer_drain(buf1, evbuffer_get_length(buf1)), ==, 0);
1773 tt_int_op(evbuffer_get_length(buf2), ==, len1+len2+2);
1774 tt_int_op(evbuffer_drain(buf2, evbuffer_get_length(buf2)), ==, 0);
1775 evbuffer_validate(buf1);
1776 evbuffer_validate(buf2);
1780 evbuffer_free(buf1);
1782 evbuffer_free(buf2);
1785 /* Some cases that we didn't get in test_evbuffer() above, for more coverage. */
1787 test_evbuffer_prepend(void *ptr)
1789 struct evbuffer *buf1 = NULL, *buf2 = NULL;
1793 buf1 = evbuffer_new();
1796 /* Case 0: The evbuffer is entirely empty. */
1797 evbuffer_prepend(buf1, "This string has 29 characters", 29);
1798 evbuffer_validate(buf1);
1800 /* Case 1: Prepend goes entirely in new chunk. */
1801 evbuffer_prepend(buf1, "Short.", 6);
1802 evbuffer_validate(buf1);
1804 /* Case 2: prepend goes entirely in first chunk. */
1805 evbuffer_drain(buf1, 6+11);
1806 evbuffer_prepend(buf1, "it", 2);
1807 evbuffer_validate(buf1);
1808 tt_assert(!memcmp(buf1->first->buffer+buf1->first->misalign,
1811 /* Case 3: prepend is split over multiple chunks. */
1812 evbuffer_prepend(buf1, "It is no longer true to say ", 28);
1813 evbuffer_validate(buf1);
1814 n = evbuffer_remove(buf1, tmp, sizeof(tmp)-1);
1815 tt_int_op(n, >=, 0);
1817 tt_str_op(tmp,==,"It is no longer true to say it has 29 characters");
1819 buf2 = evbuffer_new();
1822 /* Case 4: prepend a buffer to an empty buffer. */
1824 evbuffer_add_printf(buf1, "Here is string %d. ", n++);
1825 evbuffer_prepend_buffer(buf2, buf1);
1826 evbuffer_validate(buf2);
1828 /* Case 5: prepend a buffer to a nonempty buffer. */
1829 evbuffer_add_printf(buf1, "Here is string %d. ", n++);
1830 evbuffer_prepend_buffer(buf2, buf1);
1831 evbuffer_validate(buf2);
1832 evbuffer_validate(buf1);
1833 n = evbuffer_remove(buf2, tmp, sizeof(tmp)-1);
1834 tt_int_op(n, >=, 0);
1836 tt_str_op(tmp,==,"Here is string 1000. Here is string 999. ");
1840 evbuffer_free(buf1);
1842 evbuffer_free(buf2);
1847 test_evbuffer_peek_first_gt(void *info)
1849 struct evbuffer *buf = NULL, *tmp_buf = NULL;
1850 struct evbuffer_ptr ptr;
1851 struct evbuffer_iovec v[2];
1853 buf = evbuffer_new();
1854 tmp_buf = evbuffer_new();
1855 evbuffer_add_printf(tmp_buf, "Contents of chunk 100\n");
1856 evbuffer_add_buffer(buf, tmp_buf);
1857 evbuffer_add_printf(tmp_buf, "Contents of chunk 1\n");
1858 evbuffer_add_buffer(buf, tmp_buf);
1860 evbuffer_ptr_set(buf, &ptr, 0, EVBUFFER_PTR_SET);
1862 /** The only case that matters*/
1863 tt_int_op(evbuffer_peek(buf, -1, &ptr, NULL, 0), ==, 2);
1865 tt_int_op(evbuffer_peek(buf, -1, &ptr, v, 2), ==, 2);
1867 evbuffer_ptr_set(buf, &ptr, 20, EVBUFFER_PTR_ADD);
1868 tt_int_op(evbuffer_peek(buf, -1, &ptr, NULL, 0), ==, 2);
1869 tt_int_op(evbuffer_peek(buf, -1, &ptr, v, 2), ==, 2);
1870 tt_int_op(evbuffer_peek(buf, 2, &ptr, NULL, 0), ==, 1);
1871 tt_int_op(evbuffer_peek(buf, 2, &ptr, v, 2), ==, 1);
1872 tt_int_op(evbuffer_peek(buf, 3, &ptr, NULL, 0), ==, 2);
1873 tt_int_op(evbuffer_peek(buf, 3, &ptr, v, 2), ==, 2);
1879 evbuffer_free(tmp_buf);
1883 test_evbuffer_peek(void *info)
1885 struct evbuffer *buf = NULL, *tmp_buf = NULL;
1887 struct evbuffer_iovec v[20];
1888 struct evbuffer_ptr ptr;
1890 #define tt_iov_eq(v, s) \
1891 tt_int_op((v)->iov_len, ==, strlen(s)); \
1892 tt_assert(!memcmp((v)->iov_base, (s), strlen(s)))
1894 /* Let's make a very fragmented buffer. */
1895 buf = evbuffer_new();
1896 tmp_buf = evbuffer_new();
1897 for (i = 0; i < 16; ++i) {
1898 evbuffer_add_printf(tmp_buf, "Contents of chunk [%d]\n", i);
1899 evbuffer_add_buffer(buf, tmp_buf);
1902 /* How many chunks do we need for everything? */
1903 i = evbuffer_peek(buf, -1, NULL, NULL, 0);
1904 tt_int_op(i, ==, 16);
1906 /* Simple peek: get everything. */
1907 i = evbuffer_peek(buf, -1, NULL, v, 20);
1908 tt_int_op(i, ==, 16); /* we used only 16 chunks. */
1909 tt_iov_eq(&v[0], "Contents of chunk [0]\n");
1910 tt_iov_eq(&v[3], "Contents of chunk [3]\n");
1911 tt_iov_eq(&v[12], "Contents of chunk [12]\n");
1912 tt_iov_eq(&v[15], "Contents of chunk [15]\n");
1914 /* Just get one chunk worth. */
1915 memset(v, 0, sizeof(v));
1916 i = evbuffer_peek(buf, -1, NULL, v, 1);
1917 tt_int_op(i, ==, 1);
1918 tt_iov_eq(&v[0], "Contents of chunk [0]\n");
1919 tt_assert(v[1].iov_base == NULL);
1921 /* Suppose we want at least the first 40 bytes. */
1922 memset(v, 0, sizeof(v));
1923 i = evbuffer_peek(buf, 40, NULL, v, 16);
1924 tt_int_op(i, ==, 2);
1925 tt_iov_eq(&v[0], "Contents of chunk [0]\n");
1926 tt_iov_eq(&v[1], "Contents of chunk [1]\n");
1927 tt_assert(v[2].iov_base == NULL);
1929 /* How many chunks do we need for 100 bytes? */
1930 memset(v, 0, sizeof(v));
1931 i = evbuffer_peek(buf, 100, NULL, NULL, 0);
1932 tt_int_op(i, ==, 5);
1933 tt_assert(v[0].iov_base == NULL);
1935 /* Now we ask for more bytes than we provide chunks for */
1936 memset(v, 0, sizeof(v));
1937 i = evbuffer_peek(buf, 60, NULL, v, 1);
1938 tt_int_op(i, ==, 3);
1939 tt_iov_eq(&v[0], "Contents of chunk [0]\n");
1940 tt_assert(v[1].iov_base == NULL);
1942 /* Now we ask for more bytes than the buffer has. */
1943 memset(v, 0, sizeof(v));
1944 i = evbuffer_peek(buf, 65536, NULL, v, 20);
1945 tt_int_op(i, ==, 16); /* we used only 16 chunks. */
1946 tt_iov_eq(&v[0], "Contents of chunk [0]\n");
1947 tt_iov_eq(&v[3], "Contents of chunk [3]\n");
1948 tt_iov_eq(&v[12], "Contents of chunk [12]\n");
1949 tt_iov_eq(&v[15], "Contents of chunk [15]\n");
1950 tt_assert(v[16].iov_base == NULL);
1952 /* What happens if we try an empty buffer? */
1953 memset(v, 0, sizeof(v));
1954 i = evbuffer_peek(tmp_buf, -1, NULL, v, 20);
1955 tt_int_op(i, ==, 0);
1956 tt_assert(v[0].iov_base == NULL);
1957 memset(v, 0, sizeof(v));
1958 i = evbuffer_peek(tmp_buf, 50, NULL, v, 20);
1959 tt_int_op(i, ==, 0);
1960 tt_assert(v[0].iov_base == NULL);
1962 /* Okay, now time to have fun with pointers. */
1963 memset(v, 0, sizeof(v));
1964 evbuffer_ptr_set(buf, &ptr, 30, EVBUFFER_PTR_SET);
1965 i = evbuffer_peek(buf, 50, &ptr, v, 20);
1966 tt_int_op(i, ==, 3);
1967 tt_iov_eq(&v[0], " of chunk [1]\n");
1968 tt_iov_eq(&v[1], "Contents of chunk [2]\n");
1969 tt_iov_eq(&v[2], "Contents of chunk [3]\n"); /*more than we asked for*/
1971 /* advance to the start of another chain. */
1972 memset(v, 0, sizeof(v));
1973 evbuffer_ptr_set(buf, &ptr, 14, EVBUFFER_PTR_ADD);
1974 i = evbuffer_peek(buf, 44, &ptr, v, 20);
1975 tt_int_op(i, ==, 2);
1976 tt_iov_eq(&v[0], "Contents of chunk [2]\n");
1977 tt_iov_eq(&v[1], "Contents of chunk [3]\n"); /*more than we asked for*/
1979 /* peek at the end of the buffer */
1980 memset(v, 0, sizeof(v));
1981 tt_assert(evbuffer_ptr_set(buf, &ptr, evbuffer_get_length(buf), EVBUFFER_PTR_SET) == 0);
1982 i = evbuffer_peek(buf, 44, &ptr, v, 20);
1983 tt_int_op(i, ==, 0);
1984 tt_assert(v[0].iov_base == NULL);
1990 evbuffer_free(tmp_buf);
1993 /* Check whether evbuffer freezing works right. This is called twice,
1994 once with the argument "start" and once with the argument "end".
1995 When we test "start", we freeze the start of an evbuffer and make sure
1996 that modifying the start of the buffer doesn't work. When we test
1997 "end", we freeze the end of an evbuffer and make sure that modifying
1998 the end of the buffer doesn't work.
2001 test_evbuffer_freeze(void *ptr)
2003 struct evbuffer *buf = NULL, *tmp_buf=NULL;
2004 const char string[] = /* Year's End, Richard Wilbur */
2005 "I've known the wind by water banks to shake\n"
2006 "The late leaves down, which frozen where they fell\n"
2007 "And held in ice as dancers in a spell\n"
2008 "Fluttered all winter long into a lake...";
2009 const int start = !strcmp(ptr, "start");
2014 struct evbuffer_iovec v[1];
2017 tt_str_op(ptr, ==, "end");
2019 buf = evbuffer_new();
2020 tmp_buf = evbuffer_new();
2023 evbuffer_add(buf, string, strlen(string));
2024 evbuffer_freeze(buf, start); /* Freeze the start or the end.*/
2026 #define FREEZE_EQ(a, startcase, endcase) \
2029 tt_int_op((a), ==, (startcase)); \
2031 tt_int_op((a), ==, (endcase)); \
2036 orig_length = evbuffer_get_length(buf);
2038 /* These functions all manipulate the end of buf. */
2039 r = evbuffer_add(buf, "abc", 0);
2040 FREEZE_EQ(r, 0, -1);
2041 r = evbuffer_reserve_space(buf, 10, v, 1);
2042 FREEZE_EQ(r, 1, -1);
2044 memset(v[0].iov_base, 'X', 10);
2047 r = evbuffer_commit_space(buf, v, 1);
2048 FREEZE_EQ(r, 0, -1);
2049 r = evbuffer_add_reference(buf, string, 5, NULL, NULL);
2050 FREEZE_EQ(r, 0, -1);
2051 r = evbuffer_add_printf(buf, "Hello %s", "world");
2052 FREEZE_EQ(r, 11, -1);
2053 /* TODO: test add_buffer, add_file, read */
2056 tt_int_op(orig_length, ==, evbuffer_get_length(buf));
2058 orig_length = evbuffer_get_length(buf);
2060 /* These functions all manipulate the start of buf. */
2061 r = evbuffer_remove(buf, charbuf, 1);
2062 FREEZE_EQ(r, -1, 1);
2063 r = evbuffer_drain(buf, 3);
2064 FREEZE_EQ(r, -1, 0);
2065 r = evbuffer_prepend(buf, "dummy", 5);
2066 FREEZE_EQ(r, -1, 0);
2067 cp = evbuffer_readln(buf, NULL, EVBUFFER_EOL_LF);
2068 FREEZE_EQ(cp==NULL, 1, 0);
2071 /* TODO: Test remove_buffer, add_buffer, write, prepend_buffer */
2074 tt_int_op(orig_length, ==, evbuffer_get_length(buf));
2081 evbuffer_free(tmp_buf);
2085 test_evbuffer_add_iovec(void * ptr)
2087 struct evbuffer * buf = NULL;
2088 struct evbuffer_iovec vec[4];
2089 const char * data[] = {
2090 "Guilt resembles a sword with two edges.",
2091 "On the one hand, it cuts for Justice, imposing practical morality upon those who fear it.",
2092 "Conscience does not always adhere to rational judgment.",
2093 "Guilt is always a self-imposed burden, but it is not always rightly imposed."
2094 /* -- R.A. Salvatore, _Sojurn_ */
2096 size_t expected_length = 0;
2097 size_t returned_length = 0;
2100 buf = evbuffer_new();
2104 for (i = 0; i < 4; i++) {
2105 vec[i].iov_len = strlen(data[i]);
2106 vec[i].iov_base = (char*) data[i];
2107 expected_length += vec[i].iov_len;
2110 returned_length = evbuffer_add_iovec(buf, vec, 4);
2112 tt_int_op(returned_length, ==, evbuffer_get_length(buf));
2113 tt_int_op(evbuffer_get_length(buf), ==, expected_length);
2115 for (i = 0; i < 4; i++) {
2118 memset(charbuf, 0, 1024);
2119 evbuffer_remove(buf, charbuf, strlen(data[i]));
2120 tt_assert(strcmp(charbuf, data[i]) == 0);
2123 tt_assert(evbuffer_get_length(buf) == 0);
2131 test_evbuffer_copyout(void *dummy)
2133 const char string[] =
2134 "Still they skirmish to and fro, men my messmates on the snow "
2135 "When we headed off the aurochs turn for turn; "
2136 "When the rich Allobrogenses never kept amanuenses, "
2137 "And our only plots were piled in lakes at Berne.";
2138 /* -- Kipling, "In The Neolithic Age" */
2140 struct evbuffer_ptr ptr;
2141 struct evbuffer *buf;
2145 buf = evbuffer_new();
2148 tt_int_op(strlen(string), ==, 206);
2150 /* Ensure separate chains */
2151 evbuffer_add_reference(buf, string, 80, no_cleanup, NULL);
2152 evbuffer_add_reference(buf, string+80, 80, no_cleanup, NULL);
2153 evbuffer_add(buf, string+160, strlen(string)-160);
2155 tt_int_op(206, ==, evbuffer_get_length(buf));
2157 /* First, let's test plain old copyout. */
2159 /* Copy a little from the beginning. */
2160 tt_int_op(10, ==, evbuffer_copyout(buf, tmp, 10));
2161 tt_int_op(0, ==, memcmp(tmp, "Still they", 10));
2163 /* Now copy more than a little from the beginning */
2164 memset(tmp, 0, sizeof(tmp));
2165 tt_int_op(100, ==, evbuffer_copyout(buf, tmp, 100));
2166 tt_int_op(0, ==, memcmp(tmp, string, 100));
2168 /* Copy too much; ensure truncation. */
2169 memset(tmp, 0, sizeof(tmp));
2170 tt_int_op(206, ==, evbuffer_copyout(buf, tmp, 230));
2171 tt_int_op(0, ==, memcmp(tmp, string, 206));
2173 /* That was supposed to be nondestructive, btw */
2174 tt_int_op(206, ==, evbuffer_get_length(buf));
2176 /* Now it's time to test copyout_from! First, let's start in the
2178 evbuffer_ptr_set(buf, &ptr, 15, EVBUFFER_PTR_SET);
2179 memset(tmp, 0, sizeof(tmp));
2180 tt_int_op(10, ==, evbuffer_copyout_from(buf, &ptr, tmp, 10));
2181 tt_int_op(0, ==, memcmp(tmp, "mish to an", 10));
2183 /* Right up to the end of the first chain */
2184 memset(tmp, 0, sizeof(tmp));
2185 tt_int_op(65, ==, evbuffer_copyout_from(buf, &ptr, tmp, 65));
2186 tt_int_op(0, ==, memcmp(tmp, string+15, 65));
2188 /* Span into the second chain */
2189 memset(tmp, 0, sizeof(tmp));
2190 tt_int_op(90, ==, evbuffer_copyout_from(buf, &ptr, tmp, 90));
2191 tt_int_op(0, ==, memcmp(tmp, string+15, 90));
2193 /* Span into the third chain */
2194 memset(tmp, 0, sizeof(tmp));
2195 tt_int_op(160, ==, evbuffer_copyout_from(buf, &ptr, tmp, 160));
2196 tt_int_op(0, ==, memcmp(tmp, string+15, 160));
2199 memset(tmp, 0, sizeof(tmp));
2200 tt_int_op(206-15, ==, evbuffer_copyout_from(buf, &ptr, tmp, 999));
2201 tt_int_op(0, ==, memcmp(tmp, string+15, 206-15));
2203 /* That was supposed to be nondestructive, too */
2204 tt_int_op(206, ==, evbuffer_get_length(buf));
2212 setup_passthrough(const struct testcase_t *testcase)
2214 return testcase->setup_data;
2217 cleanup_passthrough(const struct testcase_t *testcase, void *ptr)
2223 static const struct testcase_setup_t nil_setup = {
2228 struct testcase_t evbuffer_testcases[] = {
2229 { "evbuffer", test_evbuffer, 0, NULL, NULL },
2230 { "remove_buffer_with_empty", test_evbuffer_remove_buffer_with_empty, 0, NULL, NULL },
2231 { "reserve2", test_evbuffer_reserve2, 0, NULL, NULL },
2232 { "reserve_many", test_evbuffer_reserve_many, 0, NULL, NULL },
2233 { "reserve_many2", test_evbuffer_reserve_many, 0, &nil_setup, (void*)"add" },
2234 { "reserve_many3", test_evbuffer_reserve_many, 0, &nil_setup, (void*)"fill" },
2235 { "expand", test_evbuffer_expand, 0, NULL, NULL },
2236 { "reference", test_evbuffer_reference, 0, NULL, NULL },
2237 { "iterative", test_evbuffer_iterative, 0, NULL, NULL },
2238 { "readln", test_evbuffer_readln, TT_NO_LOGS, &basic_setup, NULL },
2239 { "search_eol", test_evbuffer_search_eol, 0, NULL, NULL },
2240 { "find", test_evbuffer_find, 0, NULL, NULL },
2241 { "ptr_set", test_evbuffer_ptr_set, 0, NULL, NULL },
2242 { "search", test_evbuffer_search, 0, NULL, NULL },
2243 { "callbacks", test_evbuffer_callbacks, 0, NULL, NULL },
2244 { "add_reference", test_evbuffer_add_reference, 0, NULL, NULL },
2245 { "multicast", test_evbuffer_multicast, 0, NULL, NULL },
2246 { "multicast_drain", test_evbuffer_multicast_drain, 0, NULL, NULL },
2247 { "prepend", test_evbuffer_prepend, TT_FORK, NULL, NULL },
2248 { "peek", test_evbuffer_peek, 0, NULL, NULL },
2249 { "peek_first_gt", test_evbuffer_peek_first_gt, 0, NULL, NULL },
2250 { "freeze_start", test_evbuffer_freeze, 0, &nil_setup, (void*)"start" },
2251 { "freeze_end", test_evbuffer_freeze, 0, &nil_setup, (void*)"end" },
2252 { "add_iovec", test_evbuffer_add_iovec, 0, NULL, NULL},
2253 { "copyout", test_evbuffer_copyout, 0, NULL, NULL},
2254 { "file_segment_add_cleanup_cb", test_evbuffer_file_segment_add_cleanup_cb, 0, NULL, NULL },
2256 #define ADDFILE_TEST(name, parameters) \
2257 { name, test_evbuffer_add_file, TT_FORK|TT_NEED_BASE, \
2258 &basic_setup, (void*)(parameters) }
2260 #define ADDFILE_TEST_GROUP(name, parameters) \
2261 ADDFILE_TEST(name "_sendfile", "sendfile " parameters), \
2262 ADDFILE_TEST(name "_mmap", "mmap " parameters), \
2263 ADDFILE_TEST(name "_linear", "linear " parameters)
2265 ADDFILE_TEST_GROUP("add_file", ""),
2266 ADDFILE_TEST("add_file_nosegment", "default nosegment"),
2268 ADDFILE_TEST_GROUP("add_big_file", "bigfile"),
2269 ADDFILE_TEST("add_big_file_nosegment", "default nosegment bigfile"),
2271 ADDFILE_TEST_GROUP("add_file_offset", "bigfile map_offset"),
2272 ADDFILE_TEST("add_file_offset_nosegment",
2273 "default nosegment bigfile map_offset"),
2275 ADDFILE_TEST_GROUP("add_file_offset2", "bigfile offset_in_segment"),
2277 ADDFILE_TEST_GROUP("add_file_offset3",
2278 "bigfile offset_in_segment map_offset"),