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