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