Home | History | Annotate | Line # | Download | only in test
regress_buffer.c revision 1.2
      1  1.2  christos /*	$NetBSD: regress_buffer.c,v 1.2 2013/04/11 16:56:42 christos Exp $	*/
      2  1.1  christos /*
      3  1.1  christos  * Copyright (c) 2003-2007 Niels Provos <provos (at) citi.umich.edu>
      4  1.1  christos  * Copyright (c) 2007-2012 Niels Provos and Nick Mathewson
      5  1.1  christos  *
      6  1.1  christos  * Redistribution and use in source and binary forms, with or without
      7  1.1  christos  * modification, are permitted provided that the following conditions
      8  1.1  christos  * are met:
      9  1.1  christos  * 1. Redistributions of source code must retain the above copyright
     10  1.1  christos  *    notice, this list of conditions and the following disclaimer.
     11  1.1  christos  * 2. Redistributions in binary form must reproduce the above copyright
     12  1.1  christos  *    notice, this list of conditions and the following disclaimer in the
     13  1.1  christos  *    documentation and/or other materials provided with the distribution.
     14  1.1  christos  * 3. The name of the author may not be used to endorse or promote products
     15  1.1  christos  *    derived from this software without specific prior written permission.
     16  1.1  christos  *
     17  1.1  christos  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
     18  1.1  christos  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
     19  1.1  christos  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
     20  1.1  christos  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
     21  1.1  christos  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
     22  1.1  christos  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     23  1.1  christos  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     24  1.1  christos  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     25  1.1  christos  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
     26  1.1  christos  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     27  1.1  christos  */
     28  1.1  christos 
     29  1.1  christos #ifdef WIN32
     30  1.1  christos #include <winsock2.h>
     31  1.1  christos #include <windows.h>
     32  1.1  christos #endif
     33  1.1  christos 
     34  1.1  christos #include "event2/event-config.h"
     35  1.1  christos #include <sys/cdefs.h>
     36  1.2  christos __RCSID("$NetBSD: regress_buffer.c,v 1.2 2013/04/11 16:56:42 christos Exp $");
     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 "evbuffer-internal.h"
     63  1.1  christos #include "log-internal.h"
     64  1.1  christos 
     65  1.1  christos #include "regress.h"
     66  1.1  christos 
     67  1.1  christos /* Validates that an evbuffer is good. Returns false if it isn't, true if it
     68  1.1  christos  * is*/
     69  1.1  christos static int
     70  1.1  christos _evbuffer_validate(struct evbuffer *buf)
     71  1.1  christos {
     72  1.1  christos 	struct evbuffer_chain *chain;
     73  1.1  christos 	size_t sum = 0;
     74  1.1  christos 	int found_last_with_datap = 0;
     75  1.1  christos 
     76  1.1  christos 	if (buf->first == NULL) {
     77  1.1  christos 		tt_assert(buf->last == NULL);
     78  1.1  christos 		tt_assert(buf->total_len == 0);
     79  1.1  christos 	}
     80  1.1  christos 
     81  1.1  christos 	chain = buf->first;
     82  1.1  christos 
     83  1.1  christos 	tt_assert(buf->last_with_datap);
     84  1.1  christos 	if (buf->last_with_datap == &buf->first)
     85  1.1  christos 		found_last_with_datap = 1;
     86  1.1  christos 
     87  1.1  christos 	while (chain != NULL) {
     88  1.1  christos 		if (&chain->next == buf->last_with_datap)
     89  1.1  christos 			found_last_with_datap = 1;
     90  1.1  christos 		sum += chain->off;
     91  1.1  christos 		if (chain->next == NULL) {
     92  1.1  christos 			tt_assert(buf->last == chain);
     93  1.1  christos 		}
     94  1.1  christos 		tt_assert(chain->buffer_len >= chain->misalign + chain->off);
     95  1.1  christos 		chain = chain->next;
     96  1.1  christos 	}
     97  1.1  christos 
     98  1.1  christos 	if (buf->first)
     99  1.1  christos 		tt_assert(*buf->last_with_datap);
    100  1.1  christos 
    101  1.1  christos 	if (*buf->last_with_datap) {
    102  1.1  christos 		chain = *buf->last_with_datap;
    103  1.1  christos 		if (chain->off == 0 || buf->total_len == 0) {
    104  1.1  christos 			tt_assert(chain->off == 0)
    105  1.1  christos 			tt_assert(chain == buf->first);
    106  1.1  christos 			tt_assert(buf->total_len == 0);
    107  1.1  christos 		}
    108  1.1  christos 		chain = chain->next;
    109  1.1  christos 		while (chain != NULL) {
    110  1.1  christos 			tt_assert(chain->off == 0);
    111  1.1  christos 			chain = chain->next;
    112  1.1  christos 		}
    113  1.1  christos 	} else {
    114  1.1  christos 		tt_assert(buf->last_with_datap == &buf->first);
    115  1.1  christos 	}
    116  1.1  christos 	tt_assert(found_last_with_datap);
    117  1.1  christos 
    118  1.1  christos 	tt_assert(sum == buf->total_len);
    119  1.1  christos 	return 1;
    120  1.1  christos  end:
    121  1.1  christos 	return 0;
    122  1.1  christos }
    123  1.1  christos 
    124  1.1  christos static void
    125  1.1  christos evbuffer_get_waste(struct evbuffer *buf, size_t *allocatedp, size_t *wastedp, size_t *usedp)
    126  1.1  christos {
    127  1.1  christos 	struct evbuffer_chain *chain;
    128  1.1  christos 	size_t a, w, u;
    129  1.1  christos 	int n = 0;
    130  1.1  christos 	u = a = w = 0;
    131  1.1  christos 
    132  1.1  christos 	chain = buf->first;
    133  1.1  christos 	/* skip empty at start */
    134  1.1  christos 	while (chain && chain->off==0) {
    135  1.1  christos 		++n;
    136  1.1  christos 		a += chain->buffer_len;
    137  1.1  christos 		chain = chain->next;
    138  1.1  christos 	}
    139  1.1  christos 	/* first nonempty chain: stuff at the end only is wasted. */
    140  1.1  christos 	if (chain) {
    141  1.1  christos 		++n;
    142  1.1  christos 		a += chain->buffer_len;
    143  1.1  christos 		u += chain->off;
    144  1.1  christos 		if (chain->next && chain->next->off)
    145  1.1  christos 			w += (size_t)(chain->buffer_len - (chain->misalign + chain->off));
    146  1.1  christos 		chain = chain->next;
    147  1.1  christos 	}
    148  1.1  christos 	/* subsequent nonempty chains */
    149  1.1  christos 	while (chain && chain->off) {
    150  1.1  christos 		++n;
    151  1.1  christos 		a += chain->buffer_len;
    152  1.1  christos 		w += (size_t)chain->misalign;
    153  1.1  christos 		u += chain->off;
    154  1.1  christos 		if (chain->next && chain->next->off)
    155  1.1  christos 			w += (size_t) (chain->buffer_len - (chain->misalign + chain->off));
    156  1.1  christos 		chain = chain->next;
    157  1.1  christos 	}
    158  1.1  christos 	/* subsequent empty chains */
    159  1.1  christos 	while (chain) {
    160  1.1  christos 		++n;
    161  1.1  christos 		a += chain->buffer_len;
    162  1.1  christos 	}
    163  1.1  christos 	*allocatedp = a;
    164  1.1  christos 	*wastedp = w;
    165  1.1  christos 	*usedp = u;
    166  1.1  christos }
    167  1.1  christos 
    168  1.1  christos #define evbuffer_validate(buf)			\
    169  1.1  christos 	TT_STMT_BEGIN if (!_evbuffer_validate(buf)) TT_DIE(("Buffer format invalid")); TT_STMT_END
    170  1.1  christos 
    171  1.1  christos static void
    172  1.1  christos test_evbuffer(void *ptr)
    173  1.1  christos {
    174  1.1  christos 	static char buffer[512], *tmp;
    175  1.1  christos 	struct evbuffer *evb = evbuffer_new();
    176  1.1  christos 	struct evbuffer *evb_two = evbuffer_new();
    177  1.1  christos 	size_t sz_tmp;
    178  1.1  christos 	int i;
    179  1.1  christos 
    180  1.1  christos 	evbuffer_validate(evb);
    181  1.1  christos 	evbuffer_add_printf(evb, "%s/%d", "hello", 1);
    182  1.1  christos 	evbuffer_validate(evb);
    183  1.1  christos 
    184  1.1  christos 	tt_assert(evbuffer_get_length(evb) == 7);
    185  1.1  christos 	tt_assert(!memcmp((char*)EVBUFFER_DATA(evb), "hello/1", 1));
    186  1.1  christos 
    187  1.1  christos 	evbuffer_add_buffer(evb, evb_two);
    188  1.1  christos 	evbuffer_validate(evb);
    189  1.1  christos 
    190  1.1  christos 	evbuffer_drain(evb, strlen("hello/"));
    191  1.1  christos 	evbuffer_validate(evb);
    192  1.1  christos 	tt_assert(evbuffer_get_length(evb) == 1);
    193  1.1  christos 	tt_assert(!memcmp((char*)EVBUFFER_DATA(evb), "1", 1));
    194  1.1  christos 
    195  1.1  christos 	evbuffer_add_printf(evb_two, "%s", "/hello");
    196  1.1  christos 	evbuffer_validate(evb);
    197  1.1  christos 	evbuffer_add_buffer(evb, evb_two);
    198  1.1  christos 	evbuffer_validate(evb);
    199  1.1  christos 
    200  1.1  christos 	tt_assert(evbuffer_get_length(evb_two) == 0);
    201  1.1  christos 	tt_assert(evbuffer_get_length(evb) == 7);
    202  1.1  christos 	tt_assert(!memcmp((char*)EVBUFFER_DATA(evb), "1/hello", 7) != 0);
    203  1.1  christos 
    204  1.1  christos 	memset(buffer, 0, sizeof(buffer));
    205  1.1  christos 	evbuffer_add(evb, buffer, sizeof(buffer));
    206  1.1  christos 	evbuffer_validate(evb);
    207  1.1  christos 	tt_assert(evbuffer_get_length(evb) == 7 + 512);
    208  1.1  christos 
    209  1.1  christos 	tmp = (char *)evbuffer_pullup(evb, 7 + 512);
    210  1.1  christos 	tt_assert(tmp);
    211  1.1  christos 	tt_assert(!strncmp(tmp, "1/hello", 7));
    212  1.1  christos 	tt_assert(!memcmp(tmp + 7, buffer, sizeof(buffer)));
    213  1.1  christos 	evbuffer_validate(evb);
    214  1.1  christos 
    215  1.1  christos 	evbuffer_prepend(evb, "something", 9);
    216  1.1  christos 	evbuffer_validate(evb);
    217  1.1  christos 	evbuffer_prepend(evb, "else", 4);
    218  1.1  christos 	evbuffer_validate(evb);
    219  1.1  christos 
    220  1.1  christos 	tmp = (char *)evbuffer_pullup(evb, 4 + 9 + 7);
    221  1.1  christos 	tt_assert(!strncmp(tmp, "elsesomething1/hello", 4 + 9 + 7));
    222  1.1  christos 	evbuffer_validate(evb);
    223  1.1  christos 
    224  1.1  christos 	evbuffer_drain(evb, -1);
    225  1.1  christos 	evbuffer_validate(evb);
    226  1.1  christos 	evbuffer_drain(evb_two, -1);
    227  1.1  christos 	evbuffer_validate(evb);
    228  1.1  christos 
    229  1.1  christos 	for (i = 0; i < 3; ++i) {
    230  1.1  christos 		evbuffer_add(evb_two, buffer, sizeof(buffer));
    231  1.1  christos 		evbuffer_validate(evb_two);
    232  1.1  christos 		evbuffer_add_buffer(evb, evb_two);
    233  1.1  christos 		evbuffer_validate(evb);
    234  1.1  christos 		evbuffer_validate(evb_two);
    235  1.1  christos 	}
    236  1.1  christos 
    237  1.1  christos 	tt_assert(evbuffer_get_length(evb_two) == 0);
    238  1.1  christos 	tt_assert(evbuffer_get_length(evb) == i * sizeof(buffer));
    239  1.1  christos 
    240  1.1  christos 	/* test remove buffer */
    241  1.1  christos 	sz_tmp = (size_t)(sizeof(buffer)*2.5);
    242  1.1  christos 	evbuffer_remove_buffer(evb, evb_two, sz_tmp);
    243  1.1  christos 	tt_assert(evbuffer_get_length(evb_two) == sz_tmp);
    244  1.1  christos 	tt_assert(evbuffer_get_length(evb) == sizeof(buffer) / 2);
    245  1.1  christos 	evbuffer_validate(evb);
    246  1.1  christos 
    247  1.1  christos 	if (memcmp(evbuffer_pullup(
    248  1.1  christos 			   evb, -1), buffer, sizeof(buffer) / 2) != 0 ||
    249  1.1  christos 	    memcmp(evbuffer_pullup(
    250  1.1  christos 			   evb_two, -1), buffer, sizeof(buffer) != 0))
    251  1.1  christos 		tt_abort_msg("Pullup did not preserve content");
    252  1.1  christos 
    253  1.1  christos 	evbuffer_validate(evb);
    254  1.1  christos 
    255  1.1  christos 
    256  1.1  christos 	/* testing one-vector reserve and commit */
    257  1.1  christos 	{
    258  1.1  christos 		struct evbuffer_iovec v[1];
    259  1.1  christos 		char *buf;
    260  1.2  christos 		int ii, j, r;
    261  1.1  christos 
    262  1.2  christos 		for (ii = 0; ii < 3; ++ii) {
    263  1.1  christos 			r = evbuffer_reserve_space(evb, 10000, v, 1);
    264  1.1  christos 			tt_int_op(r, ==, 1);
    265  1.1  christos 			tt_assert(v[0].iov_len >= 10000);
    266  1.1  christos 			tt_assert(v[0].iov_base != NULL);
    267  1.1  christos 
    268  1.1  christos 			evbuffer_validate(evb);
    269  1.1  christos 			buf = v[0].iov_base;
    270  1.1  christos 			for (j = 0; j < 10000; ++j) {
    271  1.1  christos 				buf[j] = j;
    272  1.1  christos 			}
    273  1.1  christos 			evbuffer_validate(evb);
    274  1.1  christos 
    275  1.1  christos 			tt_int_op(evbuffer_commit_space(evb, v, 1), ==, 0);
    276  1.1  christos 			evbuffer_validate(evb);
    277  1.1  christos 
    278  1.1  christos 			tt_assert(evbuffer_get_length(evb) >= 10000);
    279  1.1  christos 
    280  1.1  christos 			evbuffer_drain(evb, j * 5000);
    281  1.1  christos 			evbuffer_validate(evb);
    282  1.1  christos 		}
    283  1.1  christos 	}
    284  1.1  christos 
    285  1.1  christos  end:
    286  1.1  christos 	evbuffer_free(evb);
    287  1.1  christos 	evbuffer_free(evb_two);
    288  1.1  christos }
    289  1.1  christos 
    290  1.1  christos static void
    291  1.1  christos no_cleanup(const void *data, size_t datalen, void *extra)
    292  1.1  christos {
    293  1.1  christos }
    294  1.1  christos 
    295  1.1  christos static void
    296  1.1  christos test_evbuffer_remove_buffer_with_empty(void *ptr)
    297  1.1  christos {
    298  1.1  christos     struct evbuffer *src = evbuffer_new();
    299  1.1  christos     struct evbuffer *dst = evbuffer_new();
    300  1.1  christos     char buf[2];
    301  1.1  christos 
    302  1.1  christos     evbuffer_validate(src);
    303  1.1  christos     evbuffer_validate(dst);
    304  1.1  christos 
    305  1.1  christos     /* setup the buffers */
    306  1.1  christos     /* we need more data in src than we will move later */
    307  1.1  christos     evbuffer_add_reference(src, buf, sizeof(buf), no_cleanup, NULL);
    308  1.1  christos     evbuffer_add_reference(src, buf, sizeof(buf), no_cleanup, NULL);
    309  1.1  christos     /* we need one buffer in dst and one empty buffer at the end */
    310  1.1  christos     evbuffer_add(dst, buf, sizeof(buf));
    311  1.1  christos     evbuffer_add_reference(dst, buf, 0, no_cleanup, NULL);
    312  1.1  christos 
    313  1.1  christos     evbuffer_validate(src);
    314  1.1  christos     evbuffer_validate(dst);
    315  1.1  christos 
    316  1.1  christos     /* move three bytes over */
    317  1.1  christos     evbuffer_remove_buffer(src, dst, 3);
    318  1.1  christos 
    319  1.1  christos     evbuffer_validate(src);
    320  1.1  christos     evbuffer_validate(dst);
    321  1.1  christos 
    322  1.1  christos end:
    323  1.1  christos     evbuffer_free(src);
    324  1.1  christos     evbuffer_free(dst);
    325  1.1  christos }
    326  1.1  christos 
    327  1.1  christos static void
    328  1.1  christos test_evbuffer_reserve2(void *ptr)
    329  1.1  christos {
    330  1.1  christos 	/* Test the two-vector cases of reserve/commit. */
    331  1.1  christos 	struct evbuffer *buf = evbuffer_new();
    332  1.1  christos 	int n, i;
    333  1.1  christos 	struct evbuffer_iovec v[2];
    334  1.1  christos 	size_t remaining;
    335  1.1  christos 	char *cp, *cp2;
    336  1.1  christos 
    337  1.1  christos 	/* First chunk will necessarily be one chunk. Use 512 bytes of it.*/
    338  1.1  christos 	n = evbuffer_reserve_space(buf, 1024, v, 2);
    339  1.1  christos 	tt_int_op(n, ==, 1);
    340  1.1  christos 	tt_int_op(evbuffer_get_length(buf), ==, 0);
    341  1.1  christos 	tt_assert(v[0].iov_base != NULL);
    342  1.1  christos 	tt_int_op(v[0].iov_len, >=, 1024);
    343  1.1  christos 	memset(v[0].iov_base, 'X', 512);
    344  1.1  christos 	cp = v[0].iov_base;
    345  1.1  christos 	remaining = v[0].iov_len - 512;
    346  1.1  christos 	v[0].iov_len = 512;
    347  1.1  christos 	evbuffer_validate(buf);
    348  1.1  christos 	tt_int_op(0, ==, evbuffer_commit_space(buf, v, 1));
    349  1.1  christos 	tt_int_op(evbuffer_get_length(buf), ==, 512);
    350  1.1  christos 	evbuffer_validate(buf);
    351  1.1  christos 
    352  1.1  christos 	/* Ask for another same-chunk request, in an existing chunk. Use 8
    353  1.1  christos 	 * bytes of it. */
    354  1.1  christos 	n = evbuffer_reserve_space(buf, 32, v, 2);
    355  1.1  christos 	tt_int_op(n, ==, 1);
    356  1.1  christos 	tt_assert(cp + 512 == v[0].iov_base);
    357  1.1  christos 	tt_int_op(remaining, ==, v[0].iov_len);
    358  1.1  christos 	memset(v[0].iov_base, 'Y', 8);
    359  1.1  christos 	v[0].iov_len = 8;
    360  1.1  christos 	tt_int_op(0, ==, evbuffer_commit_space(buf, v, 1));
    361  1.1  christos 	tt_int_op(evbuffer_get_length(buf), ==, 520);
    362  1.1  christos 	remaining -= 8;
    363  1.1  christos 	evbuffer_validate(buf);
    364  1.1  christos 
    365  1.1  christos 	/* Now ask for a request that will be split. Use only one byte of it,
    366  1.1  christos 	   though. */
    367  1.1  christos 	n = evbuffer_reserve_space(buf, remaining+64, v, 2);
    368  1.1  christos 	tt_int_op(n, ==, 2);
    369  1.1  christos 	tt_assert(cp + 520 == v[0].iov_base);
    370  1.1  christos 	tt_int_op(remaining, ==, v[0].iov_len);
    371  1.1  christos 	tt_assert(v[1].iov_base);
    372  1.1  christos 	tt_assert(v[1].iov_len >= 64);
    373  1.1  christos 	cp2 = v[1].iov_base;
    374  1.1  christos 	memset(v[0].iov_base, 'Z', 1);
    375  1.1  christos 	v[0].iov_len = 1;
    376  1.1  christos 	tt_int_op(0, ==, evbuffer_commit_space(buf, v, 1));
    377  1.1  christos 	tt_int_op(evbuffer_get_length(buf), ==, 521);
    378  1.1  christos 	remaining -= 1;
    379  1.1  christos 	evbuffer_validate(buf);
    380  1.1  christos 
    381  1.1  christos 	/* Now ask for a request that will be split. Use some of the first
    382  1.1  christos 	 * part and some of the second. */
    383  1.1  christos 	n = evbuffer_reserve_space(buf, remaining+64, v, 2);
    384  1.1  christos 	evbuffer_validate(buf);
    385  1.1  christos 	tt_int_op(n, ==, 2);
    386  1.1  christos 	tt_assert(cp + 521 == v[0].iov_base);
    387  1.1  christos 	tt_int_op(remaining, ==, v[0].iov_len);
    388  1.1  christos 	tt_assert(v[1].iov_base == cp2);
    389  1.1  christos 	tt_assert(v[1].iov_len >= 64);
    390  1.1  christos 	memset(v[0].iov_base, 'W', 400);
    391  1.1  christos 	v[0].iov_len = 400;
    392  1.1  christos 	memset(v[1].iov_base, 'x', 60);
    393  1.1  christos 	v[1].iov_len = 60;
    394  1.1  christos 	tt_int_op(0, ==, evbuffer_commit_space(buf, v, 2));
    395  1.1  christos 	tt_int_op(evbuffer_get_length(buf), ==, 981);
    396  1.1  christos 	evbuffer_validate(buf);
    397  1.1  christos 
    398  1.1  christos 	/* Now peek to make sure stuff got made how we like. */
    399  1.1  christos 	memset(v,0,sizeof(v));
    400  1.1  christos 	n = evbuffer_peek(buf, -1, NULL, v, 2);
    401  1.1  christos 	tt_int_op(n, ==, 2);
    402  1.1  christos 	tt_int_op(v[0].iov_len, ==, 921);
    403  1.1  christos 	tt_int_op(v[1].iov_len, ==, 60);
    404  1.1  christos 
    405  1.1  christos 	cp = v[0].iov_base;
    406  1.1  christos 	for (i=0; i<512; ++i)
    407  1.1  christos 		tt_int_op(cp[i], ==, 'X');
    408  1.1  christos 	for (i=512; i<520; ++i)
    409  1.1  christos 		tt_int_op(cp[i], ==, 'Y');
    410  1.1  christos 	for (i=520; i<521; ++i)
    411  1.1  christos 		tt_int_op(cp[i], ==, 'Z');
    412  1.1  christos 	for (i=521; i<921; ++i)
    413  1.1  christos 		tt_int_op(cp[i], ==, 'W');
    414  1.1  christos 
    415  1.1  christos 	cp = v[1].iov_base;
    416  1.1  christos 	for (i=0; i<60; ++i)
    417  1.1  christos 		tt_int_op(cp[i], ==, 'x');
    418  1.1  christos 
    419  1.1  christos end:
    420  1.1  christos 	evbuffer_free(buf);
    421  1.1  christos }
    422  1.1  christos 
    423  1.1  christos static void
    424  1.1  christos test_evbuffer_reserve_many(void *ptr)
    425  1.1  christos {
    426  1.1  christos 	/* This is a glass-box test to handle expanding a buffer with more
    427  1.1  christos 	 * chunks and reallocating chunks as needed */
    428  1.1  christos 	struct evbuffer *buf = evbuffer_new();
    429  1.1  christos 	struct evbuffer_iovec v[8];
    430  1.1  christos 	int n;
    431  1.1  christos 	size_t sz;
    432  1.1  christos 	int add_data = ptr && !strcmp(ptr, "add");
    433  1.1  christos 	int fill_first = ptr && !strcmp(ptr, "fill");
    434  1.1  christos 	char *cp1, *cp2;
    435  1.1  christos 
    436  1.1  christos 	/* When reserving the the first chunk, we just allocate it */
    437  1.1  christos 	n = evbuffer_reserve_space(buf, 128, v, 2);
    438  1.1  christos 	evbuffer_validate(buf);
    439  1.1  christos 	tt_int_op(n, ==, 1);
    440  1.1  christos 	tt_assert(v[0].iov_len >= 128);
    441  1.1  christos 	sz = v[0].iov_len;
    442  1.1  christos 	cp1 = v[0].iov_base;
    443  1.1  christos 	if (add_data) {
    444  1.1  christos 		*(char*)v[0].iov_base = 'X';
    445  1.1  christos 		v[0].iov_len = 1;
    446  1.1  christos 		n = evbuffer_commit_space(buf, v, 1);
    447  1.1  christos 		tt_int_op(n, ==, 0);
    448  1.1  christos 	} else if (fill_first) {
    449  1.1  christos 		memset(v[0].iov_base, 'X', v[0].iov_len);
    450  1.1  christos 		n = evbuffer_commit_space(buf, v, 1);
    451  1.1  christos 		tt_int_op(n, ==, 0);
    452  1.1  christos 		n = evbuffer_reserve_space(buf, 128, v, 2);
    453  1.1  christos 		tt_int_op(n, ==, 1);
    454  1.1  christos 		sz = v[0].iov_len;
    455  1.1  christos 		tt_assert(v[0].iov_base != cp1);
    456  1.1  christos 		cp1 = v[0].iov_base;
    457  1.1  christos 	}
    458  1.1  christos 
    459  1.1  christos 	/* Make another chunk get added. */
    460  1.1  christos 	n = evbuffer_reserve_space(buf, sz+128, v, 2);
    461  1.1  christos 	evbuffer_validate(buf);
    462  1.1  christos 	tt_int_op(n, ==, 2);
    463  1.1  christos 	sz = v[0].iov_len + v[1].iov_len;
    464  1.1  christos 	tt_int_op(sz, >=, v[0].iov_len+128);
    465  1.1  christos 	if (add_data) {
    466  1.1  christos 		tt_assert(v[0].iov_base == cp1 + 1);
    467  1.1  christos 	} else {
    468  1.1  christos 		tt_assert(v[0].iov_base == cp1);
    469  1.1  christos 	}
    470  1.1  christos 	cp1 = v[0].iov_base;
    471  1.1  christos 	cp2 = v[1].iov_base;
    472  1.1  christos 
    473  1.1  christos 	/* And a third chunk. */
    474  1.1  christos 	n = evbuffer_reserve_space(buf, sz+128, v, 3);
    475  1.1  christos 	evbuffer_validate(buf);
    476  1.1  christos 	tt_int_op(n, ==, 3);
    477  1.1  christos 	tt_assert(cp1 == v[0].iov_base);
    478  1.1  christos 	tt_assert(cp2 == v[1].iov_base);
    479  1.1  christos 	sz = v[0].iov_len + v[1].iov_len + v[2].iov_len;
    480  1.1  christos 
    481  1.1  christos 	/* Now force a reallocation by asking for more space in only 2
    482  1.1  christos 	 * buffers. */
    483  1.1  christos 	n = evbuffer_reserve_space(buf, sz+128, v, 2);
    484  1.1  christos 	evbuffer_validate(buf);
    485  1.1  christos 	if (add_data) {
    486  1.1  christos 		tt_int_op(n, ==, 2);
    487  1.1  christos 		tt_assert(cp1 == v[0].iov_base);
    488  1.1  christos 	} else {
    489  1.1  christos 		tt_int_op(n, ==, 1);
    490  1.1  christos 	}
    491  1.1  christos 
    492  1.1  christos end:
    493  1.1  christos 	evbuffer_free(buf);
    494  1.1  christos }
    495  1.1  christos 
    496  1.1  christos static void
    497  1.1  christos test_evbuffer_expand(void *ptr)
    498  1.1  christos {
    499  1.1  christos 	char data[4096];
    500  1.1  christos 	struct evbuffer *buf;
    501  1.1  christos 	size_t a,w,u;
    502  1.1  christos 	void *buffer;
    503  1.1  christos 
    504  1.1  christos 	memset(data, 'X', sizeof(data));
    505  1.1  christos 
    506  1.1  christos 	/* Make sure that expand() works on an empty buffer */
    507  1.1  christos 	buf = evbuffer_new();
    508  1.1  christos 	tt_int_op(evbuffer_expand(buf, 20000), ==, 0);
    509  1.1  christos 	evbuffer_validate(buf);
    510  1.1  christos 	a=w=u=0;
    511  1.1  christos 	evbuffer_get_waste(buf, &a,&w,&u);
    512  1.1  christos 	tt_assert(w == 0);
    513  1.1  christos 	tt_assert(u == 0);
    514  1.1  christos 	tt_assert(a >= 20000);
    515  1.1  christos 	tt_assert(buf->first);
    516  1.1  christos 	tt_assert(buf->first == buf->last);
    517  1.1  christos 	tt_assert(buf->first->off == 0);
    518  1.1  christos 	tt_assert(buf->first->buffer_len >= 20000);
    519  1.1  christos 
    520  1.1  christos 	/* Make sure that expand() works as a no-op when there's enough
    521  1.1  christos 	 * contiguous space already. */
    522  1.1  christos 	buffer = buf->first->buffer;
    523  1.1  christos 	evbuffer_add(buf, data, 1024);
    524  1.1  christos 	tt_int_op(evbuffer_expand(buf, 1024), ==, 0);
    525  1.1  christos 	tt_assert(buf->first->buffer == buffer);
    526  1.1  christos 	evbuffer_validate(buf);
    527  1.1  christos 	evbuffer_free(buf);
    528  1.1  christos 
    529  1.1  christos 	/* Make sure that expand() can work by moving misaligned data
    530  1.1  christos 	 * when it makes sense to do so. */
    531  1.1  christos 	buf = evbuffer_new();
    532  1.1  christos 	evbuffer_add(buf, data, 400);
    533  1.1  christos 	{
    534  1.1  christos 		int n = (int)(buf->first->buffer_len - buf->first->off - 1);
    535  1.1  christos 		tt_assert(n < (int)sizeof(data));
    536  1.1  christos 		evbuffer_add(buf, data, n);
    537  1.1  christos 	}
    538  1.1  christos 	tt_assert(buf->first == buf->last);
    539  1.1  christos 	tt_assert(buf->first->off == buf->first->buffer_len - 1);
    540  1.1  christos 	evbuffer_drain(buf, buf->first->off - 1);
    541  1.1  christos 	tt_assert(1 == evbuffer_get_length(buf));
    542  1.1  christos 	tt_assert(buf->first->misalign > 0);
    543  1.1  christos 	tt_assert(buf->first->off == 1);
    544  1.1  christos 	buffer = buf->first->buffer;
    545  1.1  christos 	tt_assert(evbuffer_expand(buf, 40) == 0);
    546  1.1  christos 	tt_assert(buf->first == buf->last);
    547  1.1  christos 	tt_assert(buf->first->off == 1);
    548  1.1  christos 	tt_assert(buf->first->buffer == buffer);
    549  1.1  christos 	tt_assert(buf->first->misalign == 0);
    550  1.1  christos 	evbuffer_validate(buf);
    551  1.1  christos 	evbuffer_free(buf);
    552  1.1  christos 
    553  1.1  christos 	/* add, expand, pull-up: This used to crash libevent. */
    554  1.1  christos 	buf = evbuffer_new();
    555  1.1  christos 
    556  1.1  christos 	evbuffer_add(buf, data, sizeof(data));
    557  1.1  christos 	evbuffer_add(buf, data, sizeof(data));
    558  1.1  christos 	evbuffer_add(buf, data, sizeof(data));
    559  1.1  christos 
    560  1.1  christos 	evbuffer_validate(buf);
    561  1.1  christos 	evbuffer_expand(buf, 1024);
    562  1.1  christos 	evbuffer_validate(buf);
    563  1.1  christos 	evbuffer_pullup(buf, -1);
    564  1.1  christos 	evbuffer_validate(buf);
    565  1.1  christos 
    566  1.1  christos end:
    567  1.1  christos 	evbuffer_free(buf);
    568  1.1  christos }
    569  1.1  christos 
    570  1.1  christos 
    571  1.1  christos static int reference_cb_called;
    572  1.1  christos static void
    573  1.1  christos reference_cb(const void *data, size_t len, void *extra)
    574  1.1  christos {
    575  1.1  christos 	tt_str_op(data, ==, "this is what we add as read-only memory.");
    576  1.1  christos 	tt_int_op(len, ==, strlen(data));
    577  1.1  christos 	tt_want(extra == (void *)0xdeadaffe);
    578  1.1  christos 	++reference_cb_called;
    579  1.1  christos end:
    580  1.1  christos 	;
    581  1.1  christos }
    582  1.1  christos 
    583  1.1  christos static void
    584  1.1  christos test_evbuffer_reference(void *ptr)
    585  1.1  christos {
    586  1.1  christos 	struct evbuffer *src = evbuffer_new();
    587  1.1  christos 	struct evbuffer *dst = evbuffer_new();
    588  1.1  christos 	struct evbuffer_iovec v[1];
    589  1.1  christos 	const char *data = "this is what we add as read-only memory.";
    590  1.1  christos 	reference_cb_called = 0;
    591  1.1  christos 
    592  1.1  christos 	tt_assert(evbuffer_add_reference(src, data, strlen(data),
    593  1.1  christos 		 reference_cb, (void *)0xdeadaffe) != -1);
    594  1.1  christos 
    595  1.1  christos 	evbuffer_reserve_space(dst, strlen(data), v, 1);
    596  1.1  christos 	tt_assert(evbuffer_remove(src, v[0].iov_base, 10) != -1);
    597  1.1  christos 
    598  1.1  christos 	evbuffer_validate(src);
    599  1.1  christos 	evbuffer_validate(dst);
    600  1.1  christos 
    601  1.1  christos 	/* make sure that we don't write data at the beginning */
    602  1.1  christos 	evbuffer_prepend(src, "aaaaa", 5);
    603  1.1  christos 	evbuffer_validate(src);
    604  1.1  christos 	evbuffer_drain(src, 5);
    605  1.1  christos 
    606  1.1  christos 	tt_assert(evbuffer_remove(src, ((char*)(v[0].iov_base)) + 10,
    607  1.1  christos 		strlen(data) - 10) != -1);
    608  1.1  christos 
    609  1.1  christos 	v[0].iov_len = strlen(data);
    610  1.1  christos 
    611  1.1  christos 	evbuffer_commit_space(dst, v, 1);
    612  1.1  christos 	evbuffer_validate(src);
    613  1.1  christos 	evbuffer_validate(dst);
    614  1.1  christos 
    615  1.1  christos 	tt_int_op(reference_cb_called, ==, 1);
    616  1.1  christos 
    617  1.1  christos 	tt_assert(!memcmp(evbuffer_pullup(dst, strlen(data)),
    618  1.1  christos 			  data, strlen(data)));
    619  1.1  christos 	evbuffer_validate(dst);
    620  1.1  christos 
    621  1.1  christos  end:
    622  1.1  christos 	evbuffer_free(dst);
    623  1.1  christos 	evbuffer_free(src);
    624  1.1  christos }
    625  1.1  christos 
    626  1.1  christos int _evbuffer_testing_use_sendfile(void);
    627  1.1  christos int _evbuffer_testing_use_mmap(void);
    628  1.1  christos int _evbuffer_testing_use_linear_file_access(void);
    629  1.1  christos 
    630  1.1  christos static void
    631  1.1  christos test_evbuffer_add_file(void *ptr)
    632  1.1  christos {
    633  1.1  christos 	const char *impl = ptr;
    634  1.1  christos 	struct evbuffer *src = evbuffer_new();
    635  1.1  christos 	const char *data = "this is what we add as file system data.";
    636  1.1  christos 	size_t datalen;
    637  1.1  christos 	const char *compare;
    638  1.1  christos 	int fd = -1;
    639  1.2  christos 	evutil_socket_t xpair[2] = {-1, -1};
    640  1.1  christos 	int r=0, n_written=0;
    641  1.1  christos 
    642  1.1  christos 	/* Add a test for a big file. XXXX */
    643  1.1  christos 
    644  1.1  christos 	tt_assert(impl);
    645  1.1  christos 	if (!strcmp(impl, "sendfile")) {
    646  1.1  christos 		if (!_evbuffer_testing_use_sendfile())
    647  1.1  christos 			tt_skip();
    648  1.1  christos 		TT_BLATHER(("Using sendfile-based implementaion"));
    649  1.1  christos 	} else if (!strcmp(impl, "mmap")) {
    650  1.1  christos 		if (!_evbuffer_testing_use_mmap())
    651  1.1  christos 			tt_skip();
    652  1.1  christos 		TT_BLATHER(("Using mmap-based implementaion"));
    653  1.1  christos 	} else if (!strcmp(impl, "linear")) {
    654  1.1  christos 		if (!_evbuffer_testing_use_linear_file_access())
    655  1.1  christos 			tt_skip();
    656  1.1  christos 		TT_BLATHER(("Using read-based implementaion"));
    657  1.1  christos 	} else {
    658  1.1  christos 		TT_DIE(("Didn't recognize the implementation"));
    659  1.1  christos 	}
    660  1.1  christos 
    661  1.1  christos 	/* Say that it drains to a fd so that we can use sendfile. */
    662  1.1  christos 	evbuffer_set_flags(src, EVBUFFER_FLAG_DRAINS_TO_FD);
    663  1.1  christos 
    664  1.1  christos #if defined(_EVENT_HAVE_SENDFILE) && defined(__sun__) && defined(__svr4__)
    665  1.1  christos 	/* We need to use a pair of AF_INET sockets, since Solaris
    666  1.1  christos 	   doesn't support sendfile() over AF_UNIX. */
    667  1.2  christos 	if (evutil_ersatz_socketpair(AF_INET, SOCK_STREAM, 0, xpair) == -1)
    668  1.1  christos 		tt_abort_msg("ersatz_socketpair failed");
    669  1.1  christos #else
    670  1.2  christos 	if (evutil_socketpair(AF_UNIX, SOCK_STREAM, 0, xpair) == -1)
    671  1.1  christos 		tt_abort_msg("socketpair failed");
    672  1.1  christos #endif
    673  1.1  christos 
    674  1.1  christos 	datalen = strlen(data);
    675  1.1  christos 	fd = regress_make_tmpfile(data, datalen);
    676  1.1  christos 
    677  1.1  christos 	tt_assert(fd != -1);
    678  1.1  christos 
    679  1.1  christos 	tt_assert(evbuffer_add_file(src, fd, 0, datalen) != -1);
    680  1.1  christos 
    681  1.1  christos 	evbuffer_validate(src);
    682  1.1  christos 
    683  1.1  christos 	while (evbuffer_get_length(src) &&
    684  1.2  christos 	    (r = evbuffer_write(src, xpair[0])) > 0) {
    685  1.1  christos 		evbuffer_validate(src);
    686  1.1  christos 		n_written += r;
    687  1.1  christos 	}
    688  1.1  christos 	tt_int_op(r, !=, -1);
    689  1.1  christos 	tt_int_op(n_written, ==, datalen);
    690  1.1  christos 
    691  1.1  christos 	evbuffer_validate(src);
    692  1.2  christos 	tt_int_op(evbuffer_read(src, xpair[1], (int)strlen(data)), ==, datalen);
    693  1.1  christos 	evbuffer_validate(src);
    694  1.1  christos 	compare = (char *)evbuffer_pullup(src, datalen);
    695  1.1  christos 	tt_assert(compare != NULL);
    696  1.1  christos 	if (memcmp(compare, data, datalen))
    697  1.1  christos 		tt_abort_msg("Data from add_file differs.");
    698  1.1  christos 
    699  1.1  christos 	evbuffer_validate(src);
    700  1.1  christos  end:
    701  1.2  christos 	if (xpair[0] >= 0)
    702  1.2  christos 		evutil_closesocket(xpair[0]);
    703  1.2  christos 	if (xpair[1] >= 0)
    704  1.2  christos 		evutil_closesocket(xpair[1]);
    705  1.1  christos 	evbuffer_free(src);
    706  1.1  christos }
    707  1.1  christos 
    708  1.1  christos #ifndef _EVENT_DISABLE_MM_REPLACEMENT
    709  1.1  christos static void *
    710  1.1  christos failing_malloc(size_t how_much)
    711  1.1  christos {
    712  1.1  christos 	errno = ENOMEM;
    713  1.1  christos 	return NULL;
    714  1.1  christos }
    715  1.1  christos #endif
    716  1.1  christos 
    717  1.1  christos static void
    718  1.1  christos test_evbuffer_readln(void *ptr)
    719  1.1  christos {
    720  1.1  christos 	struct evbuffer *evb = evbuffer_new();
    721  1.1  christos 	struct evbuffer *evb_tmp = evbuffer_new();
    722  1.1  christos 	const char *s;
    723  1.1  christos 	char *cp = NULL;
    724  1.1  christos 	size_t sz;
    725  1.1  christos 
    726  1.1  christos #define tt_line_eq(content)						\
    727  1.1  christos 	TT_STMT_BEGIN							\
    728  1.1  christos 	if (!cp || sz != strlen(content) || strcmp(cp, content)) {	\
    729  1.1  christos 		TT_DIE(("Wanted %s; got %s [%d]", content, cp, (int)sz)); \
    730  1.1  christos 	}								\
    731  1.1  christos 	TT_STMT_END
    732  1.1  christos 
    733  1.1  christos 	/* Test EOL_ANY. */
    734  1.1  christos 	s = "complex silly newline\r\n\n\r\n\n\rmore\0\n";
    735  1.1  christos 	evbuffer_add(evb, s, strlen(s)+2);
    736  1.1  christos 	evbuffer_validate(evb);
    737  1.1  christos 	cp = evbuffer_readln(evb, &sz, EVBUFFER_EOL_ANY);
    738  1.1  christos 	tt_line_eq("complex silly newline");
    739  1.1  christos 	free(cp);
    740  1.1  christos 	evbuffer_validate(evb);
    741  1.1  christos 	cp = evbuffer_readln(evb, &sz, EVBUFFER_EOL_ANY);
    742  1.1  christos 	if (!cp || sz != 5 || memcmp(cp, "more\0\0", 6))
    743  1.1  christos 		tt_abort_msg("Not as expected");
    744  1.1  christos 	tt_uint_op(evbuffer_get_length(evb), ==, 0);
    745  1.1  christos 	evbuffer_validate(evb);
    746  1.1  christos 	s = "\nno newline";
    747  1.1  christos 	evbuffer_add(evb, s, strlen(s));
    748  1.1  christos 	free(cp);
    749  1.1  christos 	evbuffer_validate(evb);
    750  1.1  christos 	cp = evbuffer_readln(evb, &sz, EVBUFFER_EOL_ANY);
    751  1.1  christos 	tt_line_eq("");
    752  1.1  christos 	free(cp);
    753  1.1  christos 	evbuffer_validate(evb);
    754  1.1  christos 	cp = evbuffer_readln(evb, &sz, EVBUFFER_EOL_ANY);
    755  1.1  christos 	tt_assert(!cp);
    756  1.1  christos 	evbuffer_validate(evb);
    757  1.1  christos 	evbuffer_drain(evb, evbuffer_get_length(evb));
    758  1.1  christos 	tt_assert(evbuffer_get_length(evb) == 0);
    759  1.1  christos 	evbuffer_validate(evb);
    760  1.1  christos 
    761  1.1  christos 	/* Test EOL_CRLF */
    762  1.1  christos 	s = "Line with\rin the middle\nLine with good crlf\r\n\nfinal\n";
    763  1.1  christos 	evbuffer_add(evb, s, strlen(s));
    764  1.1  christos 	evbuffer_validate(evb);
    765  1.1  christos 	cp = evbuffer_readln(evb, &sz, EVBUFFER_EOL_CRLF);
    766  1.1  christos 	tt_line_eq("Line with\rin the middle");
    767  1.1  christos 	free(cp);
    768  1.1  christos 	evbuffer_validate(evb);
    769  1.1  christos 
    770  1.1  christos 	cp = evbuffer_readln(evb, &sz, EVBUFFER_EOL_CRLF);
    771  1.1  christos 	tt_line_eq("Line with good crlf");
    772  1.1  christos 	free(cp);
    773  1.1  christos 	evbuffer_validate(evb);
    774  1.1  christos 
    775  1.1  christos 	cp = evbuffer_readln(evb, &sz, EVBUFFER_EOL_CRLF);
    776  1.1  christos 	tt_line_eq("");
    777  1.1  christos 	free(cp);
    778  1.1  christos 	evbuffer_validate(evb);
    779  1.1  christos 
    780  1.1  christos 	cp = evbuffer_readln(evb, &sz, EVBUFFER_EOL_CRLF);
    781  1.1  christos 	tt_line_eq("final");
    782  1.1  christos 	s = "x";
    783  1.1  christos 	evbuffer_validate(evb);
    784  1.1  christos 	evbuffer_add(evb, s, 1);
    785  1.1  christos 	evbuffer_validate(evb);
    786  1.1  christos 	free(cp);
    787  1.1  christos 	cp = evbuffer_readln(evb, &sz, EVBUFFER_EOL_CRLF);
    788  1.1  christos 	tt_assert(!cp);
    789  1.1  christos 	evbuffer_validate(evb);
    790  1.1  christos 
    791  1.1  christos 	/* Test CRLF_STRICT */
    792  1.1  christos 	s = " and a bad crlf\nand a good one\r\n\r\nMore\r";
    793  1.1  christos 	evbuffer_add(evb, s, strlen(s));
    794  1.1  christos 	evbuffer_validate(evb);
    795  1.1  christos 	cp = evbuffer_readln(evb, &sz, EVBUFFER_EOL_CRLF_STRICT);
    796  1.1  christos 	tt_line_eq("x and a bad crlf\nand a good one");
    797  1.1  christos 	free(cp);
    798  1.1  christos 	evbuffer_validate(evb);
    799  1.1  christos 
    800  1.1  christos 	cp = evbuffer_readln(evb, &sz, EVBUFFER_EOL_CRLF_STRICT);
    801  1.1  christos 	tt_line_eq("");
    802  1.1  christos 	free(cp);
    803  1.1  christos 	evbuffer_validate(evb);
    804  1.1  christos 
    805  1.1  christos 	cp = evbuffer_readln(evb, &sz, EVBUFFER_EOL_CRLF_STRICT);
    806  1.1  christos 	tt_assert(!cp);
    807  1.1  christos 	evbuffer_validate(evb);
    808  1.1  christos 	evbuffer_add(evb, "\n", 1);
    809  1.1  christos 	evbuffer_validate(evb);
    810  1.1  christos 
    811  1.1  christos 	cp = evbuffer_readln(evb, &sz, EVBUFFER_EOL_CRLF_STRICT);
    812  1.1  christos 	tt_line_eq("More");
    813  1.1  christos 	free(cp);
    814  1.1  christos 	tt_assert(evbuffer_get_length(evb) == 0);
    815  1.1  christos 	evbuffer_validate(evb);
    816  1.1  christos 
    817  1.1  christos 	s = "An internal CR\r is not an eol\r\nNor is a lack of one";
    818  1.1  christos 	evbuffer_add(evb, s, strlen(s));
    819  1.1  christos 	cp = evbuffer_readln(evb, &sz, EVBUFFER_EOL_CRLF_STRICT);
    820  1.1  christos 	tt_line_eq("An internal CR\r is not an eol");
    821  1.1  christos 	free(cp);
    822  1.1  christos 	evbuffer_validate(evb);
    823  1.1  christos 
    824  1.1  christos 	cp = evbuffer_readln(evb, &sz, EVBUFFER_EOL_CRLF_STRICT);
    825  1.1  christos 	tt_assert(!cp);
    826  1.1  christos 	evbuffer_validate(evb);
    827  1.1  christos 
    828  1.1  christos 	evbuffer_add(evb, "\r\n", 2);
    829  1.1  christos 	evbuffer_validate(evb);
    830  1.1  christos 	cp = evbuffer_readln(evb, &sz, EVBUFFER_EOL_CRLF_STRICT);
    831  1.1  christos 	tt_line_eq("Nor is a lack of one");
    832  1.1  christos 	free(cp);
    833  1.1  christos 	tt_assert(evbuffer_get_length(evb) == 0);
    834  1.1  christos 	evbuffer_validate(evb);
    835  1.1  christos 
    836  1.1  christos 	/* Test LF */
    837  1.1  christos 	s = "An\rand a nl\n\nText";
    838  1.1  christos 	evbuffer_add(evb, s, strlen(s));
    839  1.1  christos 	evbuffer_validate(evb);
    840  1.1  christos 
    841  1.1  christos 	cp = evbuffer_readln(evb, &sz, EVBUFFER_EOL_LF);
    842  1.1  christos 	tt_line_eq("An\rand a nl");
    843  1.1  christos 	free(cp);
    844  1.1  christos 	evbuffer_validate(evb);
    845  1.1  christos 
    846  1.1  christos 	cp = evbuffer_readln(evb, &sz, EVBUFFER_EOL_LF);
    847  1.1  christos 	tt_line_eq("");
    848  1.1  christos 	free(cp);
    849  1.1  christos 	evbuffer_validate(evb);
    850  1.1  christos 
    851  1.1  christos 	cp = evbuffer_readln(evb, &sz, EVBUFFER_EOL_LF);
    852  1.1  christos 	tt_assert(!cp);
    853  1.1  christos 	free(cp);
    854  1.1  christos 	evbuffer_add(evb, "\n", 1);
    855  1.1  christos 	evbuffer_validate(evb);
    856  1.1  christos 	cp = evbuffer_readln(evb, &sz, EVBUFFER_EOL_LF);
    857  1.1  christos 	tt_line_eq("Text");
    858  1.1  christos 	free(cp);
    859  1.1  christos 	evbuffer_validate(evb);
    860  1.1  christos 
    861  1.1  christos 	/* Test CRLF_STRICT - across boundaries*/
    862  1.1  christos 	s = " and a bad crlf\nand a good one\r";
    863  1.1  christos 	evbuffer_add(evb_tmp, s, strlen(s));
    864  1.1  christos 	evbuffer_validate(evb);
    865  1.1  christos 	evbuffer_add_buffer(evb, evb_tmp);
    866  1.1  christos 	evbuffer_validate(evb);
    867  1.1  christos 	s = "\n\r";
    868  1.1  christos 	evbuffer_add(evb_tmp, s, strlen(s));
    869  1.1  christos 	evbuffer_validate(evb);
    870  1.1  christos 	evbuffer_add_buffer(evb, evb_tmp);
    871  1.1  christos 	evbuffer_validate(evb);
    872  1.1  christos 	s = "\nMore\r";
    873  1.1  christos 	evbuffer_add(evb_tmp, s, strlen(s));
    874  1.1  christos 	evbuffer_validate(evb);
    875  1.1  christos 	evbuffer_add_buffer(evb, evb_tmp);
    876  1.1  christos 	evbuffer_validate(evb);
    877  1.1  christos 
    878  1.1  christos 	cp = evbuffer_readln(evb, &sz, EVBUFFER_EOL_CRLF_STRICT);
    879  1.1  christos 	tt_line_eq(" and a bad crlf\nand a good one");
    880  1.1  christos 	free(cp);
    881  1.1  christos 	evbuffer_validate(evb);
    882  1.1  christos 
    883  1.1  christos 	cp = evbuffer_readln(evb, &sz, EVBUFFER_EOL_CRLF_STRICT);
    884  1.1  christos 	tt_line_eq("");
    885  1.1  christos 	free(cp);
    886  1.1  christos 	evbuffer_validate(evb);
    887  1.1  christos 
    888  1.1  christos 	cp = evbuffer_readln(evb, &sz, EVBUFFER_EOL_CRLF_STRICT);
    889  1.1  christos 	tt_assert(!cp);
    890  1.1  christos 	free(cp);
    891  1.1  christos 	evbuffer_validate(evb);
    892  1.1  christos 	evbuffer_add(evb, "\n", 1);
    893  1.1  christos 	evbuffer_validate(evb);
    894  1.1  christos 	cp = evbuffer_readln(evb, &sz, EVBUFFER_EOL_CRLF_STRICT);
    895  1.1  christos 	tt_line_eq("More");
    896  1.1  christos 	free(cp); cp = NULL;
    897  1.1  christos 	evbuffer_validate(evb);
    898  1.1  christos 	tt_assert(evbuffer_get_length(evb) == 0);
    899  1.1  christos 
    900  1.1  christos 	/* Test memory problem*/
    901  1.1  christos 	s = "one line\ntwo line\nblue line";
    902  1.1  christos 	evbuffer_add(evb_tmp, s, strlen(s));
    903  1.1  christos 	evbuffer_validate(evb);
    904  1.1  christos 	evbuffer_add_buffer(evb, evb_tmp);
    905  1.1  christos 	evbuffer_validate(evb);
    906  1.1  christos 
    907  1.1  christos 	cp = evbuffer_readln(evb, &sz, EVBUFFER_EOL_LF);
    908  1.1  christos 	tt_line_eq("one line");
    909  1.1  christos 	free(cp); cp = NULL;
    910  1.1  christos 	evbuffer_validate(evb);
    911  1.1  christos 
    912  1.1  christos 	/* the next call to readline should fail */
    913  1.1  christos #ifndef _EVENT_DISABLE_MM_REPLACEMENT
    914  1.1  christos 	event_set_mem_functions(failing_malloc, realloc, free);
    915  1.1  christos 	cp = evbuffer_readln(evb, &sz, EVBUFFER_EOL_LF);
    916  1.1  christos 	tt_assert(cp == NULL);
    917  1.1  christos 	evbuffer_validate(evb);
    918  1.1  christos 
    919  1.1  christos 	/* now we should get the next line back */
    920  1.1  christos 	event_set_mem_functions(malloc, realloc, free);
    921  1.1  christos #endif
    922  1.1  christos 	cp = evbuffer_readln(evb, &sz, EVBUFFER_EOL_LF);
    923  1.1  christos 	tt_line_eq("two line");
    924  1.1  christos 	free(cp); cp = NULL;
    925  1.1  christos 	evbuffer_validate(evb);
    926  1.1  christos 
    927  1.1  christos  end:
    928  1.1  christos 	evbuffer_free(evb);
    929  1.1  christos 	evbuffer_free(evb_tmp);
    930  1.1  christos 	if (cp) free(cp);
    931  1.1  christos }
    932  1.1  christos 
    933  1.1  christos static void
    934  1.1  christos test_evbuffer_search_eol(void *ptr)
    935  1.1  christos {
    936  1.1  christos 	struct evbuffer *buf = evbuffer_new();
    937  1.1  christos 	struct evbuffer_ptr ptr1, ptr2;
    938  1.1  christos 	const char *s;
    939  1.1  christos 	size_t eol_len;
    940  1.1  christos 
    941  1.1  christos 	s = "string! \r\n\r\nx\n";
    942  1.1  christos 	evbuffer_add(buf, s, strlen(s));
    943  1.1  christos 	eol_len = -1;
    944  1.1  christos 	ptr1 = evbuffer_search_eol(buf, NULL, &eol_len, EVBUFFER_EOL_CRLF);
    945  1.1  christos 	tt_int_op(ptr1.pos, ==, 8);
    946  1.1  christos 	tt_int_op(eol_len, ==, 2);
    947  1.1  christos 
    948  1.1  christos 	eol_len = -1;
    949  1.1  christos 	ptr2 = evbuffer_search_eol(buf, &ptr1, &eol_len, EVBUFFER_EOL_CRLF);
    950  1.1  christos 	tt_int_op(ptr2.pos, ==, 8);
    951  1.1  christos 	tt_int_op(eol_len, ==, 2);
    952  1.1  christos 
    953  1.1  christos 	evbuffer_ptr_set(buf, &ptr1, 1, EVBUFFER_PTR_ADD);
    954  1.1  christos 	eol_len = -1;
    955  1.1  christos 	ptr2 = evbuffer_search_eol(buf, &ptr1, &eol_len, EVBUFFER_EOL_CRLF);
    956  1.1  christos 	tt_int_op(ptr2.pos, ==, 9);
    957  1.1  christos 	tt_int_op(eol_len, ==, 1);
    958  1.1  christos 
    959  1.1  christos 	eol_len = -1;
    960  1.1  christos 	ptr2 = evbuffer_search_eol(buf, &ptr1, &eol_len, EVBUFFER_EOL_CRLF_STRICT);
    961  1.1  christos 	tt_int_op(ptr2.pos, ==, 10);
    962  1.1  christos 	tt_int_op(eol_len, ==, 2);
    963  1.1  christos 
    964  1.1  christos 	eol_len = -1;
    965  1.1  christos 	ptr1 = evbuffer_search_eol(buf, NULL, &eol_len, EVBUFFER_EOL_LF);
    966  1.1  christos 	tt_int_op(ptr1.pos, ==, 9);
    967  1.1  christos 	tt_int_op(eol_len, ==, 1);
    968  1.1  christos 
    969  1.1  christos 	eol_len = -1;
    970  1.1  christos 	ptr2 = evbuffer_search_eol(buf, &ptr1, &eol_len, EVBUFFER_EOL_LF);
    971  1.1  christos 	tt_int_op(ptr2.pos, ==, 9);
    972  1.1  christos 	tt_int_op(eol_len, ==, 1);
    973  1.1  christos 
    974  1.1  christos 	evbuffer_ptr_set(buf, &ptr1, 1, EVBUFFER_PTR_ADD);
    975  1.1  christos 	eol_len = -1;
    976  1.1  christos 	ptr2 = evbuffer_search_eol(buf, &ptr1, &eol_len, EVBUFFER_EOL_LF);
    977  1.1  christos 	tt_int_op(ptr2.pos, ==, 11);
    978  1.1  christos 	tt_int_op(eol_len, ==, 1);
    979  1.1  christos 
    980  1.1  christos end:
    981  1.1  christos 	evbuffer_free(buf);
    982  1.1  christos }
    983  1.1  christos 
    984  1.1  christos static void
    985  1.1  christos test_evbuffer_iterative(void *ptr)
    986  1.1  christos {
    987  1.1  christos 	struct evbuffer *buf = evbuffer_new();
    988  1.1  christos 	const char *abc = "abcdefghijklmnopqrstvuwxyzabcdefghijklmnopqrstvuwxyzabcdefghijklmnopqrstvuwxyzabcdefghijklmnopqrstvuwxyz";
    989  1.1  christos 	unsigned i, j, sum, n;
    990  1.1  christos 
    991  1.1  christos 	sum = 0;
    992  1.1  christos 	n = 0;
    993  1.1  christos 	for (i = 0; i < 1000; ++i) {
    994  1.1  christos 		for (j = 1; j < strlen(abc); ++j) {
    995  1.2  christos 			evbuffer_add_printf(buf, "%*.*s", j, j, abc);
    996  1.1  christos 
    997  1.1  christos 			/* Only check for rep violations every so often.
    998  1.1  christos 			   Walking over the whole list of chains can get
    999  1.1  christos 			   pretty expensive as it gets long.
   1000  1.1  christos 			 */
   1001  1.1  christos 			if ((n % 337) == 0)
   1002  1.1  christos 				evbuffer_validate(buf);
   1003  1.1  christos 
   1004  1.1  christos 			sum += j;
   1005  1.1  christos 			n++;
   1006  1.1  christos 		}
   1007  1.1  christos 	}
   1008  1.1  christos 	evbuffer_validate(buf);
   1009  1.1  christos 
   1010  1.1  christos 	tt_uint_op(sum, ==, evbuffer_get_length(buf));
   1011  1.1  christos 
   1012  1.1  christos 	{
   1013  1.1  christos 		size_t a,w,u;
   1014  1.1  christos 		a=w=u=0;
   1015  1.1  christos 		evbuffer_get_waste(buf, &a, &w, &u);
   1016  1.1  christos 		if (0)
   1017  1.1  christos 			printf("Allocated: %u.\nWasted: %u.\nUsed: %u.",
   1018  1.1  christos 			    (unsigned)a, (unsigned)w, (unsigned)u);
   1019  1.1  christos 		tt_assert( ((double)w)/a < .125);
   1020  1.1  christos 	}
   1021  1.1  christos  end:
   1022  1.1  christos 	evbuffer_free(buf);
   1023  1.1  christos 
   1024  1.1  christos }
   1025  1.1  christos 
   1026  1.1  christos static void
   1027  1.1  christos test_evbuffer_find(void *ptr)
   1028  1.1  christos {
   1029  1.1  christos 	u_char* p;
   1030  1.1  christos 	const char* test1 = "1234567890\r\n";
   1031  1.1  christos 	const char* test2 = "1234567890\r";
   1032  1.1  christos #define EVBUFFER_INITIAL_LENGTH 256
   1033  1.1  christos 	char test3[EVBUFFER_INITIAL_LENGTH];
   1034  1.1  christos 	unsigned int i;
   1035  1.1  christos 	struct evbuffer * buf = evbuffer_new();
   1036  1.1  christos 
   1037  1.1  christos 	tt_assert(buf);
   1038  1.1  christos 
   1039  1.1  christos 	/* make sure evbuffer_find doesn't match past the end of the buffer */
   1040  1.2  christos 	evbuffer_add(buf, __UNCONST(test1), strlen(test1));
   1041  1.1  christos 	evbuffer_validate(buf);
   1042  1.1  christos 	evbuffer_drain(buf, strlen(test1));
   1043  1.1  christos 	evbuffer_validate(buf);
   1044  1.2  christos 	evbuffer_add(buf, __UNCONST(test2), strlen(test2));
   1045  1.1  christos 	evbuffer_validate(buf);
   1046  1.2  christos 	p = evbuffer_find(buf, __UNCONST("\r\n"), 2);
   1047  1.1  christos 	tt_want(p == NULL);
   1048  1.1  christos 
   1049  1.1  christos 	/*
   1050  1.1  christos 	 * drain the buffer and do another find; in r309 this would
   1051  1.1  christos 	 * read past the allocated buffer causing a valgrind error.
   1052  1.1  christos 	 */
   1053  1.1  christos 	evbuffer_drain(buf, strlen(test2));
   1054  1.1  christos 	evbuffer_validate(buf);
   1055  1.1  christos 	for (i = 0; i < EVBUFFER_INITIAL_LENGTH; ++i)
   1056  1.1  christos 		test3[i] = 'a';
   1057  1.1  christos 	test3[EVBUFFER_INITIAL_LENGTH - 1] = 'x';
   1058  1.1  christos 	evbuffer_add(buf, (u_char *)test3, EVBUFFER_INITIAL_LENGTH);
   1059  1.1  christos 	evbuffer_validate(buf);
   1060  1.2  christos 	p = evbuffer_find(buf, __UNCONST("xy"), 2);
   1061  1.1  christos 	tt_want(p == NULL);
   1062  1.1  christos 
   1063  1.1  christos 	/* simple test for match at end of allocated buffer */
   1064  1.2  christos 	p = evbuffer_find(buf, __UNCONST("ax"), 2);
   1065  1.1  christos 	tt_assert(p != NULL);
   1066  1.1  christos 	tt_want(strncmp((char*)p, "ax", 2) == 0);
   1067  1.1  christos 
   1068  1.1  christos end:
   1069  1.1  christos 	if (buf)
   1070  1.1  christos 		evbuffer_free(buf);
   1071  1.1  christos }
   1072  1.1  christos 
   1073  1.1  christos static void
   1074  1.1  christos test_evbuffer_ptr_set(void *ptr)
   1075  1.1  christos {
   1076  1.1  christos 	struct evbuffer *buf = evbuffer_new();
   1077  1.1  christos 	struct evbuffer_ptr pos;
   1078  1.1  christos 	struct evbuffer_iovec v[1];
   1079  1.1  christos 
   1080  1.1  christos 	tt_assert(buf);
   1081  1.1  christos 
   1082  1.1  christos 	/* create some chains */
   1083  1.1  christos 	evbuffer_reserve_space(buf, 5000, v, 1);
   1084  1.1  christos 	v[0].iov_len = 5000;
   1085  1.1  christos 	memset(v[0].iov_base, 1, v[0].iov_len);
   1086  1.1  christos 	evbuffer_commit_space(buf, v, 1);
   1087  1.1  christos 	evbuffer_validate(buf);
   1088  1.1  christos 
   1089  1.1  christos 	evbuffer_reserve_space(buf, 4000, v, 1);
   1090  1.1  christos 	v[0].iov_len = 4000;
   1091  1.1  christos 	memset(v[0].iov_base, 2, v[0].iov_len);
   1092  1.1  christos 	evbuffer_commit_space(buf, v, 1);
   1093  1.1  christos 
   1094  1.1  christos 	evbuffer_reserve_space(buf, 3000, v, 1);
   1095  1.1  christos 	v[0].iov_len = 3000;
   1096  1.1  christos 	memset(v[0].iov_base, 3, v[0].iov_len);
   1097  1.1  christos 	evbuffer_commit_space(buf, v, 1);
   1098  1.1  christos 	evbuffer_validate(buf);
   1099  1.1  christos 
   1100  1.1  christos 	tt_int_op(evbuffer_get_length(buf), ==, 12000);
   1101  1.1  christos 
   1102  1.1  christos 	tt_assert(evbuffer_ptr_set(buf, &pos, 13000, EVBUFFER_PTR_SET) == -1);
   1103  1.1  christos 	tt_assert(pos.pos == -1);
   1104  1.1  christos 	tt_assert(evbuffer_ptr_set(buf, &pos, 0, EVBUFFER_PTR_SET) == 0);
   1105  1.1  christos 	tt_assert(pos.pos == 0);
   1106  1.1  christos 	tt_assert(evbuffer_ptr_set(buf, &pos, 13000, EVBUFFER_PTR_ADD) == -1);
   1107  1.1  christos 
   1108  1.1  christos 	tt_assert(evbuffer_ptr_set(buf, &pos, 0, EVBUFFER_PTR_SET) == 0);
   1109  1.1  christos 	tt_assert(pos.pos == 0);
   1110  1.1  christos 	tt_assert(evbuffer_ptr_set(buf, &pos, 10000, EVBUFFER_PTR_ADD) == 0);
   1111  1.1  christos 	tt_assert(pos.pos == 10000);
   1112  1.1  christos 	tt_assert(evbuffer_ptr_set(buf, &pos, 1000, EVBUFFER_PTR_ADD) == 0);
   1113  1.1  christos 	tt_assert(pos.pos == 11000);
   1114  1.1  christos 	tt_assert(evbuffer_ptr_set(buf, &pos, 1000, EVBUFFER_PTR_ADD) == -1);
   1115  1.1  christos 	tt_assert(pos.pos == -1);
   1116  1.1  christos 
   1117  1.1  christos end:
   1118  1.1  christos 	if (buf)
   1119  1.1  christos 		evbuffer_free(buf);
   1120  1.1  christos }
   1121  1.1  christos 
   1122  1.1  christos static void
   1123  1.1  christos test_evbuffer_search(void *ptr)
   1124  1.1  christos {
   1125  1.1  christos 	struct evbuffer *buf = evbuffer_new();
   1126  1.1  christos 	struct evbuffer *tmp = evbuffer_new();
   1127  1.1  christos 	struct evbuffer_ptr pos, end;
   1128  1.1  christos 
   1129  1.1  christos 	tt_assert(buf);
   1130  1.1  christos 	tt_assert(tmp);
   1131  1.1  christos 
   1132  1.1  christos 	/* set up our chains */
   1133  1.1  christos 	evbuffer_add_printf(tmp, "hello");  /* 5 chars */
   1134  1.1  christos 	evbuffer_add_buffer(buf, tmp);
   1135  1.1  christos 	evbuffer_add_printf(tmp, "foo");    /* 3 chars */
   1136  1.1  christos 	evbuffer_add_buffer(buf, tmp);
   1137  1.1  christos 	evbuffer_add_printf(tmp, "cat");    /* 3 chars */
   1138  1.1  christos 	evbuffer_add_buffer(buf, tmp);
   1139  1.1  christos 	evbuffer_add_printf(tmp, "attack");
   1140  1.1  christos 	evbuffer_add_buffer(buf, tmp);
   1141  1.1  christos 
   1142  1.1  christos 	pos = evbuffer_search(buf, "attack", 6, NULL);
   1143  1.1  christos 	tt_int_op(pos.pos, ==, 11);
   1144  1.1  christos 	pos = evbuffer_search(buf, "attacker", 8, NULL);
   1145  1.1  christos 	tt_int_op(pos.pos, ==, -1);
   1146  1.1  christos 
   1147  1.1  christos 	/* test continuing search */
   1148  1.1  christos 	pos = evbuffer_search(buf, "oc", 2, NULL);
   1149  1.1  christos 	tt_int_op(pos.pos, ==, 7);
   1150  1.1  christos 	pos = evbuffer_search(buf, "cat", 3, &pos);
   1151  1.1  christos 	tt_int_op(pos.pos, ==, 8);
   1152  1.1  christos 	pos = evbuffer_search(buf, "tacking", 7, &pos);
   1153  1.1  christos 	tt_int_op(pos.pos, ==, -1);
   1154  1.1  christos 
   1155  1.1  christos 	evbuffer_ptr_set(buf, &pos, 5, EVBUFFER_PTR_SET);
   1156  1.1  christos 	pos = evbuffer_search(buf, "foo", 3, &pos);
   1157  1.1  christos 	tt_int_op(pos.pos, ==, 5);
   1158  1.1  christos 
   1159  1.1  christos 	evbuffer_ptr_set(buf, &pos, 2, EVBUFFER_PTR_ADD);
   1160  1.1  christos 	pos = evbuffer_search(buf, "tat", 3, &pos);
   1161  1.1  christos 	tt_int_op(pos.pos, ==, 10);
   1162  1.1  christos 
   1163  1.1  christos 	/* test bounded search. */
   1164  1.1  christos 	/* Set "end" to the first t in "attack". */
   1165  1.1  christos 	evbuffer_ptr_set(buf, &end, 12, EVBUFFER_PTR_SET);
   1166  1.1  christos 	pos = evbuffer_search_range(buf, "foo", 3, NULL, &end);
   1167  1.1  christos 	tt_int_op(pos.pos, ==, 5);
   1168  1.1  christos 	pos = evbuffer_search_range(buf, "foocata", 7, NULL, &end);
   1169  1.1  christos 	tt_int_op(pos.pos, ==, 5);
   1170  1.1  christos 	pos = evbuffer_search_range(buf, "foocatat", 8, NULL, &end);
   1171  1.1  christos 	tt_int_op(pos.pos, ==, -1);
   1172  1.1  christos 	pos = evbuffer_search_range(buf, "ack", 3, NULL, &end);
   1173  1.1  christos 	tt_int_op(pos.pos, ==, -1);
   1174  1.1  christos 
   1175  1.1  christos 
   1176  1.1  christos end:
   1177  1.1  christos 	if (buf)
   1178  1.1  christos 		evbuffer_free(buf);
   1179  1.1  christos 	if (tmp)
   1180  1.1  christos 		evbuffer_free(tmp);
   1181  1.1  christos }
   1182  1.1  christos 
   1183  1.1  christos static void
   1184  1.1  christos log_change_callback(struct evbuffer *buffer,
   1185  1.1  christos     const struct evbuffer_cb_info *cbinfo,
   1186  1.1  christos     void *arg)
   1187  1.1  christos {
   1188  1.1  christos 
   1189  1.1  christos 	size_t old_len = cbinfo->orig_size;
   1190  1.1  christos 	size_t new_len = old_len + cbinfo->n_added - cbinfo->n_deleted;
   1191  1.1  christos 	struct evbuffer *out = arg;
   1192  1.1  christos 	evbuffer_add_printf(out, "%lu->%lu; ", (unsigned long)old_len,
   1193  1.1  christos 			    (unsigned long)new_len);
   1194  1.1  christos }
   1195  1.1  christos static void
   1196  1.1  christos self_draining_callback(struct evbuffer *evbuffer, size_t old_len,
   1197  1.1  christos 		size_t new_len, void *arg)
   1198  1.1  christos {
   1199  1.1  christos 	if (new_len > old_len)
   1200  1.1  christos 		evbuffer_drain(evbuffer, new_len);
   1201  1.1  christos }
   1202  1.1  christos 
   1203  1.1  christos static void
   1204  1.1  christos test_evbuffer_callbacks(void *ptr)
   1205  1.1  christos {
   1206  1.1  christos 	struct evbuffer *buf = evbuffer_new();
   1207  1.1  christos 	struct evbuffer *buf_out1 = evbuffer_new();
   1208  1.1  christos 	struct evbuffer *buf_out2 = evbuffer_new();
   1209  1.1  christos 	struct evbuffer_cb_entry *cb1, *cb2;
   1210  1.1  christos 
   1211  1.1  christos 	tt_assert(buf);
   1212  1.1  christos 	tt_assert(buf_out1);
   1213  1.1  christos 	tt_assert(buf_out2);
   1214  1.1  christos 
   1215  1.1  christos 	cb1 = evbuffer_add_cb(buf, log_change_callback, buf_out1);
   1216  1.1  christos 	cb2 = evbuffer_add_cb(buf, log_change_callback, buf_out2);
   1217  1.1  christos 
   1218  1.1  christos 	/* Let's run through adding and deleting some stuff from the buffer
   1219  1.1  christos 	 * and turning the callbacks on and off and removing them.  The callback
   1220  1.1  christos 	 * adds a summary of length changes to buf_out1/buf_out2 when called. */
   1221  1.1  christos 	/* size: 0-> 36. */
   1222  1.1  christos 	evbuffer_add_printf(buf, "The %d magic words are spotty pudding", 2);
   1223  1.1  christos 	evbuffer_validate(buf);
   1224  1.1  christos 	evbuffer_cb_clear_flags(buf, cb2, EVBUFFER_CB_ENABLED);
   1225  1.1  christos 	evbuffer_drain(buf, 10); /*36->26*/
   1226  1.1  christos 	evbuffer_validate(buf);
   1227  1.1  christos 	evbuffer_prepend(buf, "Hello", 5);/*26->31*/
   1228  1.1  christos 	evbuffer_cb_set_flags(buf, cb2, EVBUFFER_CB_ENABLED);
   1229  1.1  christos 	evbuffer_add_reference(buf, "Goodbye", 7, NULL, NULL); /*31->38*/
   1230  1.1  christos 	evbuffer_remove_cb_entry(buf, cb1);
   1231  1.1  christos 	evbuffer_validate(buf);
   1232  1.1  christos 	evbuffer_drain(buf, evbuffer_get_length(buf)); /*38->0*/;
   1233  1.1  christos 	tt_assert(-1 == evbuffer_remove_cb(buf, log_change_callback, NULL));
   1234  1.1  christos 	evbuffer_add(buf, "X", 1); /* 0->1 */
   1235  1.1  christos 	tt_assert(!evbuffer_remove_cb(buf, log_change_callback, buf_out2));
   1236  1.1  christos 	evbuffer_validate(buf);
   1237  1.1  christos 
   1238  1.1  christos 	tt_str_op(evbuffer_pullup(buf_out1, -1), ==,
   1239  1.1  christos 		  "0->36; 36->26; 26->31; 31->38; ");
   1240  1.1  christos 	tt_str_op(evbuffer_pullup(buf_out2, -1), ==,
   1241  1.1  christos 		  "0->36; 31->38; 38->0; 0->1; ");
   1242  1.1  christos 	evbuffer_drain(buf_out1, evbuffer_get_length(buf_out1));
   1243  1.1  christos 	evbuffer_drain(buf_out2, evbuffer_get_length(buf_out2));
   1244  1.1  christos 	/* Let's test the obsolete buffer_setcb function too. */
   1245  1.1  christos 	cb1 = evbuffer_add_cb(buf, log_change_callback, buf_out1);
   1246  1.1  christos 	tt_assert(cb1 != NULL);
   1247  1.1  christos 	cb2 = evbuffer_add_cb(buf, log_change_callback, buf_out2);
   1248  1.1  christos 	tt_assert(cb2 != NULL);
   1249  1.1  christos 	evbuffer_setcb(buf, self_draining_callback, NULL);
   1250  1.1  christos 	evbuffer_add_printf(buf, "This should get drained right away.");
   1251  1.1  christos 	tt_uint_op(evbuffer_get_length(buf), ==, 0);
   1252  1.1  christos 	tt_uint_op(evbuffer_get_length(buf_out1), ==, 0);
   1253  1.1  christos 	tt_uint_op(evbuffer_get_length(buf_out2), ==, 0);
   1254  1.1  christos 	evbuffer_setcb(buf, NULL, NULL);
   1255  1.1  christos 	evbuffer_add_printf(buf, "This will not.");
   1256  1.1  christos 	tt_str_op(evbuffer_pullup(buf, -1), ==, "This will not.");
   1257  1.1  christos 	evbuffer_validate(buf);
   1258  1.1  christos 	evbuffer_drain(buf, evbuffer_get_length(buf));
   1259  1.1  christos 	evbuffer_validate(buf);
   1260  1.1  christos #if 0
   1261  1.1  christos 	/* Now let's try a suspended callback. */
   1262  1.1  christos 	cb1 = evbuffer_add_cb(buf, log_change_callback, buf_out1);
   1263  1.1  christos 	cb2 = evbuffer_add_cb(buf, log_change_callback, buf_out2);
   1264  1.1  christos 	evbuffer_cb_suspend(buf,cb2);
   1265  1.1  christos 	evbuffer_prepend(buf,"Hello world",11); /*0->11*/
   1266  1.1  christos 	evbuffer_validate(buf);
   1267  1.1  christos 	evbuffer_cb_suspend(buf,cb1);
   1268  1.1  christos 	evbuffer_add(buf,"more",4); /* 11->15 */
   1269  1.1  christos 	evbuffer_cb_unsuspend(buf,cb2);
   1270  1.1  christos 	evbuffer_drain(buf, 4); /* 15->11 */
   1271  1.1  christos 	evbuffer_cb_unsuspend(buf,cb1);
   1272  1.1  christos 	evbuffer_drain(buf, evbuffer_get_length(buf)); /* 11->0 */
   1273  1.1  christos 
   1274  1.1  christos 	tt_str_op(evbuffer_pullup(buf_out1, -1), ==,
   1275  1.1  christos 		  "0->11; 11->11; 11->0; ");
   1276  1.1  christos 	tt_str_op(evbuffer_pullup(buf_out2, -1), ==,
   1277  1.1  christos 		  "0->15; 15->11; 11->0; ");
   1278  1.1  christos #endif
   1279  1.1  christos 
   1280  1.1  christos  end:
   1281  1.1  christos 	if (buf)
   1282  1.1  christos 		evbuffer_free(buf);
   1283  1.1  christos 	if (buf_out1)
   1284  1.1  christos 		evbuffer_free(buf_out1);
   1285  1.1  christos 	if (buf_out2)
   1286  1.1  christos 		evbuffer_free(buf_out2);
   1287  1.1  christos }
   1288  1.1  christos 
   1289  1.1  christos static int ref_done_cb_called_count = 0;
   1290  1.1  christos static void *ref_done_cb_called_with = NULL;
   1291  1.1  christos static const void *ref_done_cb_called_with_data = NULL;
   1292  1.1  christos static size_t ref_done_cb_called_with_len = 0;
   1293  1.1  christos static void ref_done_cb(const void *data, size_t len, void *info)
   1294  1.1  christos {
   1295  1.1  christos 	++ref_done_cb_called_count;
   1296  1.1  christos 	ref_done_cb_called_with = info;
   1297  1.1  christos 	ref_done_cb_called_with_data = data;
   1298  1.1  christos 	ref_done_cb_called_with_len = len;
   1299  1.1  christos }
   1300  1.1  christos 
   1301  1.1  christos static void
   1302  1.1  christos test_evbuffer_add_reference(void *ptr)
   1303  1.1  christos {
   1304  1.1  christos 	const char chunk1[] = "If you have found the answer to such a problem";
   1305  1.1  christos 	const char chunk2[] = "you ought to write it up for publication";
   1306  1.1  christos 			  /* -- Knuth's "Notes on the Exercises" from TAOCP */
   1307  1.1  christos 	char tmp[16];
   1308  1.1  christos 	size_t len1 = strlen(chunk1), len2=strlen(chunk2);
   1309  1.1  christos 
   1310  1.1  christos 	struct evbuffer *buf1 = NULL, *buf2 = NULL;
   1311  1.1  christos 
   1312  1.1  christos 	buf1 = evbuffer_new();
   1313  1.1  christos 	tt_assert(buf1);
   1314  1.1  christos 
   1315  1.1  christos 	evbuffer_add_reference(buf1, chunk1, len1, ref_done_cb, (void*)111);
   1316  1.1  christos 	evbuffer_add(buf1, ", ", 2);
   1317  1.1  christos 	evbuffer_add_reference(buf1, chunk2, len2, ref_done_cb, (void*)222);
   1318  1.1  christos 	tt_int_op(evbuffer_get_length(buf1), ==, len1+len2+2);
   1319  1.1  christos 
   1320  1.1  christos 	/* Make sure we can drain a little from a reference. */
   1321  1.1  christos 	tt_int_op(evbuffer_remove(buf1, tmp, 6), ==, 6);
   1322  1.1  christos 	tt_int_op(memcmp(tmp, "If you", 6), ==, 0);
   1323  1.1  christos 	tt_int_op(evbuffer_remove(buf1, tmp, 5), ==, 5);
   1324  1.1  christos 	tt_int_op(memcmp(tmp, " have", 5), ==, 0);
   1325  1.1  christos 
   1326  1.1  christos 	/* Make sure that prepending does not meddle with immutable data */
   1327  1.1  christos 	tt_int_op(evbuffer_prepend(buf1, "I have ", 7), ==, 0);
   1328  1.1  christos 	tt_int_op(memcmp(chunk1, "If you", 6), ==, 0);
   1329  1.1  christos 	evbuffer_validate(buf1);
   1330  1.1  christos 
   1331  1.1  christos 	/* Make sure that when the chunk is over, the callback is invoked. */
   1332  1.1  christos 	evbuffer_drain(buf1, 7); /* Remove prepended stuff. */
   1333  1.1  christos 	evbuffer_drain(buf1, len1-11-1); /* remove all but one byte of chunk1 */
   1334  1.1  christos 	tt_int_op(ref_done_cb_called_count, ==, 0);
   1335  1.1  christos 	evbuffer_remove(buf1, tmp, 1);
   1336  1.1  christos 	tt_int_op(tmp[0], ==, 'm');
   1337  1.1  christos 	tt_assert(ref_done_cb_called_with == (void*)111);
   1338  1.1  christos 	tt_assert(ref_done_cb_called_with_data == chunk1);
   1339  1.1  christos 	tt_assert(ref_done_cb_called_with_len == len1);
   1340  1.1  christos 	tt_int_op(ref_done_cb_called_count, ==, 1);
   1341  1.1  christos 	evbuffer_validate(buf1);
   1342  1.1  christos 
   1343  1.1  christos 	/* Drain some of the remaining chunk, then add it to another buffer */
   1344  1.1  christos 	evbuffer_drain(buf1, 6); /* Remove the ", you ". */
   1345  1.1  christos 	buf2 = evbuffer_new();
   1346  1.1  christos 	tt_assert(buf2);
   1347  1.1  christos 	tt_int_op(ref_done_cb_called_count, ==, 1);
   1348  1.1  christos 	evbuffer_add(buf2, "I ", 2);
   1349  1.1  christos 
   1350  1.1  christos 	evbuffer_add_buffer(buf2, buf1);
   1351  1.1  christos 	tt_int_op(ref_done_cb_called_count, ==, 1);
   1352  1.1  christos 	evbuffer_remove(buf2, tmp, 16);
   1353  1.1  christos 	tt_int_op(memcmp("I ought to write", tmp, 16), ==, 0);
   1354  1.1  christos 	evbuffer_drain(buf2, evbuffer_get_length(buf2));
   1355  1.1  christos 	tt_int_op(ref_done_cb_called_count, ==, 2);
   1356  1.1  christos 	tt_assert(ref_done_cb_called_with == (void*)222);
   1357  1.1  christos 	evbuffer_validate(buf2);
   1358  1.1  christos 
   1359  1.1  christos 	/* Now add more stuff to buf1 and make sure that it gets removed on
   1360  1.1  christos 	 * free. */
   1361  1.1  christos 	evbuffer_add(buf1, "You shake and shake the ", 24);
   1362  1.1  christos 	evbuffer_add_reference(buf1, "ketchup bottle", 14, ref_done_cb,
   1363  1.1  christos 	    (void*)3333);
   1364  1.1  christos 	evbuffer_add(buf1, ". Nothing comes and then a lot'll.", 42);
   1365  1.1  christos 	evbuffer_free(buf1);
   1366  1.1  christos 	buf1 = NULL;
   1367  1.1  christos 	tt_int_op(ref_done_cb_called_count, ==, 3);
   1368  1.1  christos 	tt_assert(ref_done_cb_called_with == (void*)3333);
   1369  1.1  christos 
   1370  1.1  christos end:
   1371  1.1  christos 	if (buf1)
   1372  1.1  christos 		evbuffer_free(buf1);
   1373  1.1  christos 	if (buf2)
   1374  1.1  christos 		evbuffer_free(buf2);
   1375  1.1  christos }
   1376  1.1  christos 
   1377  1.1  christos /* Some cases that we didn't get in test_evbuffer() above, for more coverage. */
   1378  1.1  christos static void
   1379  1.1  christos test_evbuffer_prepend(void *ptr)
   1380  1.1  christos {
   1381  1.1  christos 	struct evbuffer *buf1 = NULL, *buf2 = NULL;
   1382  1.1  christos 	char tmp[128];
   1383  1.1  christos 	int n;
   1384  1.1  christos 
   1385  1.1  christos 	buf1 = evbuffer_new();
   1386  1.1  christos 	tt_assert(buf1);
   1387  1.1  christos 
   1388  1.1  christos 	/* Case 0: The evbuffer is entirely empty. */
   1389  1.1  christos 	evbuffer_prepend(buf1, "This string has 29 characters", 29);
   1390  1.1  christos 	evbuffer_validate(buf1);
   1391  1.1  christos 
   1392  1.1  christos 	/* Case 1: Prepend goes entirely in new chunk. */
   1393  1.1  christos 	evbuffer_prepend(buf1, "Short.", 6);
   1394  1.1  christos 	evbuffer_validate(buf1);
   1395  1.1  christos 
   1396  1.1  christos 	/* Case 2: prepend goes entirely in first chunk. */
   1397  1.1  christos 	evbuffer_drain(buf1, 6+11);
   1398  1.1  christos 	evbuffer_prepend(buf1, "it", 2);
   1399  1.1  christos 	evbuffer_validate(buf1);
   1400  1.1  christos 	tt_assert(!memcmp(buf1->first->buffer+buf1->first->misalign,
   1401  1.1  christos 		"it has", 6));
   1402  1.1  christos 
   1403  1.1  christos 	/* Case 3: prepend is split over multiple chunks. */
   1404  1.1  christos 	evbuffer_prepend(buf1, "It is no longer true to say ", 28);
   1405  1.1  christos 	evbuffer_validate(buf1);
   1406  1.1  christos 	n = evbuffer_remove(buf1, tmp, sizeof(tmp)-1);
   1407  1.1  christos 	tmp[n]='\0';
   1408  1.1  christos 	tt_str_op(tmp,==,"It is no longer true to say it has 29 characters");
   1409  1.1  christos 
   1410  1.1  christos 	buf2 = evbuffer_new();
   1411  1.1  christos 	tt_assert(buf2);
   1412  1.1  christos 
   1413  1.1  christos 	/* Case 4: prepend a buffer to an empty buffer. */
   1414  1.1  christos 	n = 999;
   1415  1.1  christos 	evbuffer_add_printf(buf1, "Here is string %d. ", n++);
   1416  1.1  christos 	evbuffer_prepend_buffer(buf2, buf1);
   1417  1.1  christos 	evbuffer_validate(buf2);
   1418  1.1  christos 
   1419  1.1  christos 	/* Case 5: prepend a buffer to a nonempty buffer. */
   1420  1.1  christos 	evbuffer_add_printf(buf1, "Here is string %d. ", n++);
   1421  1.1  christos 	evbuffer_prepend_buffer(buf2, buf1);
   1422  1.1  christos 	evbuffer_validate(buf2);
   1423  1.1  christos 	evbuffer_validate(buf1);
   1424  1.1  christos 	n = evbuffer_remove(buf2, tmp, sizeof(tmp)-1);
   1425  1.1  christos 	tmp[n]='\0';
   1426  1.1  christos 	tt_str_op(tmp,==,"Here is string 1000. Here is string 999. ");
   1427  1.1  christos 
   1428  1.1  christos end:
   1429  1.1  christos 	if (buf1)
   1430  1.1  christos 		evbuffer_free(buf1);
   1431  1.1  christos 	if (buf2)
   1432  1.1  christos 		evbuffer_free(buf2);
   1433  1.1  christos 
   1434  1.1  christos }
   1435  1.1  christos 
   1436  1.1  christos static void
   1437  1.1  christos test_evbuffer_peek(void *info)
   1438  1.1  christos {
   1439  1.1  christos 	struct evbuffer *buf = NULL, *tmp_buf = NULL;
   1440  1.1  christos 	int i;
   1441  1.1  christos 	struct evbuffer_iovec v[20];
   1442  1.1  christos 	struct evbuffer_ptr ptr;
   1443  1.1  christos 
   1444  1.1  christos #define tt_iov_eq(v, s)						\
   1445  1.1  christos 	tt_int_op((v)->iov_len, ==, strlen(s));			\
   1446  1.1  christos 	tt_assert(!memcmp((v)->iov_base, (s), strlen(s)))
   1447  1.1  christos 
   1448  1.1  christos 	/* Let's make a very fragmented buffer. */
   1449  1.1  christos 	buf = evbuffer_new();
   1450  1.1  christos 	tmp_buf = evbuffer_new();
   1451  1.1  christos 	for (i = 0; i < 16; ++i) {
   1452  1.1  christos 		evbuffer_add_printf(tmp_buf, "Contents of chunk [%d]\n", i);
   1453  1.1  christos 		evbuffer_add_buffer(buf, tmp_buf);
   1454  1.1  christos 	}
   1455  1.1  christos 
   1456  1.1  christos 	/* How many chunks do we need for everything? */
   1457  1.1  christos 	i = evbuffer_peek(buf, -1, NULL, NULL, 0);
   1458  1.1  christos 	tt_int_op(i, ==, 16);
   1459  1.1  christos 
   1460  1.1  christos 	/* Simple peek: get everything. */
   1461  1.1  christos 	i = evbuffer_peek(buf, -1, NULL, v, 20);
   1462  1.1  christos 	tt_int_op(i, ==, 16); /* we used only 16 chunks. */
   1463  1.1  christos 	tt_iov_eq(&v[0], "Contents of chunk [0]\n");
   1464  1.1  christos 	tt_iov_eq(&v[3], "Contents of chunk [3]\n");
   1465  1.1  christos 	tt_iov_eq(&v[12], "Contents of chunk [12]\n");
   1466  1.1  christos 	tt_iov_eq(&v[15], "Contents of chunk [15]\n");
   1467  1.1  christos 
   1468  1.1  christos 	/* Just get one chunk worth. */
   1469  1.1  christos 	memset(v, 0, sizeof(v));
   1470  1.1  christos 	i = evbuffer_peek(buf, -1, NULL, v, 1);
   1471  1.1  christos 	tt_int_op(i, ==, 1);
   1472  1.1  christos 	tt_iov_eq(&v[0], "Contents of chunk [0]\n");
   1473  1.1  christos 	tt_assert(v[1].iov_base == NULL);
   1474  1.1  christos 
   1475  1.1  christos 	/* Suppose we want at least the first 40 bytes. */
   1476  1.1  christos 	memset(v, 0, sizeof(v));
   1477  1.1  christos 	i = evbuffer_peek(buf, 40, NULL, v, 16);
   1478  1.1  christos 	tt_int_op(i, ==, 2);
   1479  1.1  christos 	tt_iov_eq(&v[0], "Contents of chunk [0]\n");
   1480  1.1  christos 	tt_iov_eq(&v[1], "Contents of chunk [1]\n");
   1481  1.1  christos 	tt_assert(v[2].iov_base == NULL);
   1482  1.1  christos 
   1483  1.1  christos 	/* How many chunks do we need for 100 bytes? */
   1484  1.1  christos 	memset(v, 0, sizeof(v));
   1485  1.1  christos 	i = evbuffer_peek(buf, 100, NULL, NULL, 0);
   1486  1.1  christos 	tt_int_op(i, ==, 5);
   1487  1.1  christos 	tt_assert(v[0].iov_base == NULL);
   1488  1.1  christos 
   1489  1.1  christos 	/* Now we ask for more bytes than we provide chunks for */
   1490  1.1  christos 	memset(v, 0, sizeof(v));
   1491  1.1  christos 	i = evbuffer_peek(buf, 60, NULL, v, 1);
   1492  1.1  christos 	tt_int_op(i, ==, 3);
   1493  1.1  christos 	tt_iov_eq(&v[0], "Contents of chunk [0]\n");
   1494  1.1  christos 	tt_assert(v[1].iov_base == NULL);
   1495  1.1  christos 
   1496  1.1  christos 	/* Now we ask for more bytes than the buffer has. */
   1497  1.1  christos 	memset(v, 0, sizeof(v));
   1498  1.1  christos 	i = evbuffer_peek(buf, 65536, NULL, v, 20);
   1499  1.1  christos 	tt_int_op(i, ==, 16); /* we used only 16 chunks. */
   1500  1.1  christos 	tt_iov_eq(&v[0], "Contents of chunk [0]\n");
   1501  1.1  christos 	tt_iov_eq(&v[3], "Contents of chunk [3]\n");
   1502  1.1  christos 	tt_iov_eq(&v[12], "Contents of chunk [12]\n");
   1503  1.1  christos 	tt_iov_eq(&v[15], "Contents of chunk [15]\n");
   1504  1.1  christos 	tt_assert(v[16].iov_base == NULL);
   1505  1.1  christos 
   1506  1.1  christos 	/* What happens if we try an empty buffer? */
   1507  1.1  christos 	memset(v, 0, sizeof(v));
   1508  1.1  christos 	i = evbuffer_peek(tmp_buf, -1, NULL, v, 20);
   1509  1.1  christos 	tt_int_op(i, ==, 0);
   1510  1.1  christos 	tt_assert(v[0].iov_base == NULL);
   1511  1.1  christos 	memset(v, 0, sizeof(v));
   1512  1.1  christos 	i = evbuffer_peek(tmp_buf, 50, NULL, v, 20);
   1513  1.1  christos 	tt_int_op(i, ==, 0);
   1514  1.1  christos 	tt_assert(v[0].iov_base == NULL);
   1515  1.1  christos 
   1516  1.1  christos 	/* Okay, now time to have fun with pointers. */
   1517  1.1  christos 	memset(v, 0, sizeof(v));
   1518  1.1  christos 	evbuffer_ptr_set(buf, &ptr, 30, EVBUFFER_PTR_SET);
   1519  1.1  christos 	i = evbuffer_peek(buf, 50, &ptr, v, 20);
   1520  1.1  christos 	tt_int_op(i, ==, 3);
   1521  1.1  christos 	tt_iov_eq(&v[0], " of chunk [1]\n");
   1522  1.1  christos 	tt_iov_eq(&v[1], "Contents of chunk [2]\n");
   1523  1.1  christos 	tt_iov_eq(&v[2], "Contents of chunk [3]\n"); /*more than we asked for*/
   1524  1.1  christos 
   1525  1.1  christos 	/* advance to the start of another chain. */
   1526  1.1  christos 	memset(v, 0, sizeof(v));
   1527  1.1  christos 	evbuffer_ptr_set(buf, &ptr, 14, EVBUFFER_PTR_ADD);
   1528  1.1  christos 	i = evbuffer_peek(buf, 44, &ptr, v, 20);
   1529  1.1  christos 	tt_int_op(i, ==, 2);
   1530  1.1  christos 	tt_iov_eq(&v[0], "Contents of chunk [2]\n");
   1531  1.1  christos 	tt_iov_eq(&v[1], "Contents of chunk [3]\n"); /*more than we asked for*/
   1532  1.1  christos 
   1533  1.1  christos end:
   1534  1.1  christos 	if (buf)
   1535  1.1  christos 		evbuffer_free(buf);
   1536  1.1  christos 	if (tmp_buf)
   1537  1.1  christos 		evbuffer_free(tmp_buf);
   1538  1.1  christos }
   1539  1.1  christos 
   1540  1.1  christos /* Check whether evbuffer freezing works right.  This is called twice,
   1541  1.1  christos    once with the argument "start" and once with the argument "end".
   1542  1.1  christos    When we test "start", we freeze the start of an evbuffer and make sure
   1543  1.1  christos    that modifying the start of the buffer doesn't work.  When we test
   1544  1.1  christos    "end", we freeze the end of an evbuffer and make sure that modifying
   1545  1.1  christos    the end of the buffer doesn't work.
   1546  1.1  christos  */
   1547  1.1  christos static void
   1548  1.1  christos test_evbuffer_freeze(void *ptr)
   1549  1.1  christos {
   1550  1.1  christos 	struct evbuffer *buf = NULL, *tmp_buf=NULL;
   1551  1.1  christos 	const char string[] = /* Year's End, Richard Wilbur */
   1552  1.1  christos 	    "I've known the wind by water banks to shake\n"
   1553  1.1  christos 	    "The late leaves down, which frozen where they fell\n"
   1554  1.1  christos 	    "And held in ice as dancers in a spell\n"
   1555  1.1  christos 	    "Fluttered all winter long into a lake...";
   1556  1.1  christos 	const int start = !strcmp(ptr, "start");
   1557  1.1  christos 	char *cp;
   1558  1.1  christos 	char charbuf[128];
   1559  1.1  christos 	int r;
   1560  1.1  christos 	size_t orig_length;
   1561  1.1  christos 	struct evbuffer_iovec v[1];
   1562  1.1  christos 
   1563  1.1  christos 	if (!start)
   1564  1.1  christos 		tt_str_op(ptr, ==, "end");
   1565  1.1  christos 
   1566  1.1  christos 	buf = evbuffer_new();
   1567  1.1  christos 	tmp_buf = evbuffer_new();
   1568  1.1  christos 	tt_assert(tmp_buf);
   1569  1.1  christos 
   1570  1.1  christos 	evbuffer_add(buf, string, strlen(string));
   1571  1.1  christos 	evbuffer_freeze(buf, start); /* Freeze the start or the end.*/
   1572  1.1  christos 
   1573  1.1  christos #define FREEZE_EQ(a, startcase, endcase)		\
   1574  1.1  christos 	do {						\
   1575  1.1  christos 	    if (start) {				\
   1576  1.1  christos 		    tt_int_op((a), ==, (startcase));	\
   1577  1.1  christos 	    } else {					\
   1578  1.1  christos 		    tt_int_op((a), ==, (endcase));	\
   1579  1.1  christos 	    }						\
   1580  1.2  christos 	} while (/*CONSTCOND*/0)
   1581  1.1  christos 
   1582  1.1  christos 
   1583  1.1  christos 	orig_length = evbuffer_get_length(buf);
   1584  1.1  christos 
   1585  1.1  christos 	/* These functions all manipulate the end of buf. */
   1586  1.1  christos 	r = evbuffer_add(buf, "abc", 0);
   1587  1.1  christos 	FREEZE_EQ(r, 0, -1);
   1588  1.1  christos 	r = evbuffer_reserve_space(buf, 10, v, 1);
   1589  1.1  christos 	FREEZE_EQ(r, 1, -1);
   1590  1.1  christos 	if (r == 0) {
   1591  1.1  christos 		memset(v[0].iov_base, 'X', 10);
   1592  1.1  christos 		v[0].iov_len = 10;
   1593  1.1  christos 	}
   1594  1.1  christos 	r = evbuffer_commit_space(buf, v, 1);
   1595  1.1  christos 	FREEZE_EQ(r, 0, -1);
   1596  1.1  christos 	r = evbuffer_add_reference(buf, string, 5, NULL, NULL);
   1597  1.1  christos 	FREEZE_EQ(r, 0, -1);
   1598  1.1  christos 	r = evbuffer_add_printf(buf, "Hello %s", "world");
   1599  1.1  christos 	FREEZE_EQ(r, 11, -1);
   1600  1.1  christos 	/* TODO: test add_buffer, add_file, read */
   1601  1.1  christos 
   1602  1.1  christos 	if (!start)
   1603  1.1  christos 		tt_int_op(orig_length, ==, evbuffer_get_length(buf));
   1604  1.1  christos 
   1605  1.1  christos 	orig_length = evbuffer_get_length(buf);
   1606  1.1  christos 
   1607  1.1  christos 	/* These functions all manipulate the start of buf. */
   1608  1.1  christos 	r = evbuffer_remove(buf, charbuf, 1);
   1609  1.1  christos 	FREEZE_EQ(r, -1, 1);
   1610  1.1  christos 	r = evbuffer_drain(buf, 3);
   1611  1.1  christos 	FREEZE_EQ(r, -1, 0);
   1612  1.1  christos 	r = evbuffer_prepend(buf, "dummy", 5);
   1613  1.1  christos 	FREEZE_EQ(r, -1, 0);
   1614  1.1  christos 	cp = evbuffer_readln(buf, NULL, EVBUFFER_EOL_LF);
   1615  1.1  christos 	FREEZE_EQ(cp==NULL, 1, 0);
   1616  1.1  christos 	if (cp)
   1617  1.1  christos 		free(cp);
   1618  1.1  christos 	/* TODO: Test remove_buffer, add_buffer, write, prepend_buffer */
   1619  1.1  christos 
   1620  1.1  christos 	if (start)
   1621  1.1  christos 		tt_int_op(orig_length, ==, evbuffer_get_length(buf));
   1622  1.1  christos 
   1623  1.1  christos end:
   1624  1.1  christos 	if (buf)
   1625  1.1  christos 		evbuffer_free(buf);
   1626  1.1  christos 
   1627  1.1  christos 	if (tmp_buf)
   1628  1.1  christos 		evbuffer_free(tmp_buf);
   1629  1.1  christos }
   1630  1.1  christos 
   1631  1.1  christos static void *
   1632  1.1  christos setup_passthrough(const struct testcase_t *testcase)
   1633  1.1  christos {
   1634  1.1  christos 	return testcase->setup_data;
   1635  1.1  christos }
   1636  1.1  christos static int
   1637  1.1  christos cleanup_passthrough(const struct testcase_t *testcase, void *ptr)
   1638  1.1  christos {
   1639  1.1  christos 	(void) ptr;
   1640  1.1  christos 	return 1;
   1641  1.1  christos }
   1642  1.1  christos 
   1643  1.1  christos static const struct testcase_setup_t nil_setup = {
   1644  1.1  christos 	setup_passthrough,
   1645  1.1  christos 	cleanup_passthrough
   1646  1.1  christos };
   1647  1.1  christos 
   1648  1.1  christos struct testcase_t evbuffer_testcases[] = {
   1649  1.1  christos 	{ "evbuffer", test_evbuffer, 0, NULL, NULL },
   1650  1.1  christos 	{ "remove_buffer_with_empty", test_evbuffer_remove_buffer_with_empty, 0, NULL, NULL },
   1651  1.1  christos 	{ "reserve2", test_evbuffer_reserve2, 0, NULL, NULL },
   1652  1.1  christos 	{ "reserve_many", test_evbuffer_reserve_many, 0, NULL, NULL },
   1653  1.2  christos 	{ "reserve_many2", test_evbuffer_reserve_many, 0, &nil_setup, __UNCONST("add") },
   1654  1.2  christos 	{ "reserve_many3", test_evbuffer_reserve_many, 0, &nil_setup, __UNCONST("fill") },
   1655  1.1  christos 	{ "expand", test_evbuffer_expand, 0, NULL, NULL },
   1656  1.1  christos 	{ "reference", test_evbuffer_reference, 0, NULL, NULL },
   1657  1.1  christos 	{ "iterative", test_evbuffer_iterative, 0, NULL, NULL },
   1658  1.1  christos 	{ "readln", test_evbuffer_readln, TT_NO_LOGS, &basic_setup, NULL },
   1659  1.1  christos 	{ "search_eol", test_evbuffer_search_eol, 0, NULL, NULL },
   1660  1.1  christos 	{ "find", test_evbuffer_find, 0, NULL, NULL },
   1661  1.1  christos 	{ "ptr_set", test_evbuffer_ptr_set, 0, NULL, NULL },
   1662  1.1  christos 	{ "search", test_evbuffer_search, 0, NULL, NULL },
   1663  1.1  christos 	{ "callbacks", test_evbuffer_callbacks, 0, NULL, NULL },
   1664  1.1  christos 	{ "add_reference", test_evbuffer_add_reference, 0, NULL, NULL },
   1665  1.1  christos 	{ "prepend", test_evbuffer_prepend, TT_FORK, NULL, NULL },
   1666  1.1  christos 	{ "peek", test_evbuffer_peek, 0, NULL, NULL },
   1667  1.2  christos 	{ "freeze_start", test_evbuffer_freeze, 0, &nil_setup, __UNCONST("start") },
   1668  1.2  christos 	{ "freeze_end", test_evbuffer_freeze, 0, &nil_setup, __UNCONST("end") },
   1669  1.1  christos 	/* TODO: need a temp file implementation for Windows */
   1670  1.1  christos 	{ "add_file_sendfile", test_evbuffer_add_file, TT_FORK, &nil_setup,
   1671  1.2  christos 	  __UNCONST("sendfile") },
   1672  1.1  christos 	{ "add_file_mmap", test_evbuffer_add_file, TT_FORK, &nil_setup,
   1673  1.2  christos 	  __UNCONST("mmap") },
   1674  1.1  christos 	{ "add_file_linear", test_evbuffer_add_file, TT_FORK, &nil_setup,
   1675  1.2  christos 	  __UNCONST("linear") },
   1676  1.1  christos 
   1677  1.1  christos 	END_OF_TESTCASES
   1678  1.1  christos };
   1679