ipc/chromium/src/third_party/libevent/test/regress_buffer.c

changeset 0
6474c204b198
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/ipc/chromium/src/third_party/libevent/test/regress_buffer.c	Wed Dec 31 06:09:35 2014 +0100
     1.3 @@ -0,0 +1,1677 @@
     1.4 +/*
     1.5 + * Copyright (c) 2003-2007 Niels Provos <provos@citi.umich.edu>
     1.6 + * Copyright (c) 2007-2012 Niels Provos and Nick Mathewson
     1.7 + *
     1.8 + * Redistribution and use in source and binary forms, with or without
     1.9 + * modification, are permitted provided that the following conditions
    1.10 + * are met:
    1.11 + * 1. Redistributions of source code must retain the above copyright
    1.12 + *    notice, this list of conditions and the following disclaimer.
    1.13 + * 2. Redistributions in binary form must reproduce the above copyright
    1.14 + *    notice, this list of conditions and the following disclaimer in the
    1.15 + *    documentation and/or other materials provided with the distribution.
    1.16 + * 3. The name of the author may not be used to endorse or promote products
    1.17 + *    derived from this software without specific prior written permission.
    1.18 + *
    1.19 + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
    1.20 + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
    1.21 + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
    1.22 + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
    1.23 + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
    1.24 + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
    1.25 + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
    1.26 + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
    1.27 + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
    1.28 + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
    1.29 + */
    1.30 +
    1.31 +#ifdef WIN32
    1.32 +#include <winsock2.h>
    1.33 +#include <windows.h>
    1.34 +#endif
    1.35 +
    1.36 +#include "event2/event-config.h"
    1.37 +
    1.38 +#include <sys/types.h>
    1.39 +#include <sys/stat.h>
    1.40 +#ifdef _EVENT_HAVE_SYS_TIME_H
    1.41 +#include <sys/time.h>
    1.42 +#endif
    1.43 +#include <sys/queue.h>
    1.44 +#ifndef WIN32
    1.45 +#include <sys/socket.h>
    1.46 +#include <sys/wait.h>
    1.47 +#include <signal.h>
    1.48 +#include <unistd.h>
    1.49 +#include <netdb.h>
    1.50 +#endif
    1.51 +#include <stdlib.h>
    1.52 +#include <stdio.h>
    1.53 +#include <string.h>
    1.54 +#include <errno.h>
    1.55 +#include <assert.h>
    1.56 +
    1.57 +#include "event2/event.h"
    1.58 +#include "event2/buffer.h"
    1.59 +#include "event2/buffer_compat.h"
    1.60 +#include "event2/util.h"
    1.61 +
    1.62 +#include "evbuffer-internal.h"
    1.63 +#include "log-internal.h"
    1.64 +
    1.65 +#include "regress.h"
    1.66 +
    1.67 +/* Validates that an evbuffer is good. Returns false if it isn't, true if it
    1.68 + * is*/
    1.69 +static int
    1.70 +_evbuffer_validate(struct evbuffer *buf)
    1.71 +{
    1.72 +	struct evbuffer_chain *chain;
    1.73 +	size_t sum = 0;
    1.74 +	int found_last_with_datap = 0;
    1.75 +
    1.76 +	if (buf->first == NULL) {
    1.77 +		tt_assert(buf->last == NULL);
    1.78 +		tt_assert(buf->total_len == 0);
    1.79 +	}
    1.80 +
    1.81 +	chain = buf->first;
    1.82 +
    1.83 +	tt_assert(buf->last_with_datap);
    1.84 +	if (buf->last_with_datap == &buf->first)
    1.85 +		found_last_with_datap = 1;
    1.86 +
    1.87 +	while (chain != NULL) {
    1.88 +		if (&chain->next == buf->last_with_datap)
    1.89 +			found_last_with_datap = 1;
    1.90 +		sum += chain->off;
    1.91 +		if (chain->next == NULL) {
    1.92 +			tt_assert(buf->last == chain);
    1.93 +		}
    1.94 +		tt_assert(chain->buffer_len >= chain->misalign + chain->off);
    1.95 +		chain = chain->next;
    1.96 +	}
    1.97 +
    1.98 +	if (buf->first)
    1.99 +		tt_assert(*buf->last_with_datap);
   1.100 +
   1.101 +	if (*buf->last_with_datap) {
   1.102 +		chain = *buf->last_with_datap;
   1.103 +		if (chain->off == 0 || buf->total_len == 0) {
   1.104 +			tt_assert(chain->off == 0)
   1.105 +			tt_assert(chain == buf->first);
   1.106 +			tt_assert(buf->total_len == 0);
   1.107 +		}
   1.108 +		chain = chain->next;
   1.109 +		while (chain != NULL) {
   1.110 +			tt_assert(chain->off == 0);
   1.111 +			chain = chain->next;
   1.112 +		}
   1.113 +	} else {
   1.114 +		tt_assert(buf->last_with_datap == &buf->first);
   1.115 +	}
   1.116 +	tt_assert(found_last_with_datap);
   1.117 +
   1.118 +	tt_assert(sum == buf->total_len);
   1.119 +	return 1;
   1.120 + end:
   1.121 +	return 0;
   1.122 +}
   1.123 +
   1.124 +static void
   1.125 +evbuffer_get_waste(struct evbuffer *buf, size_t *allocatedp, size_t *wastedp, size_t *usedp)
   1.126 +{
   1.127 +	struct evbuffer_chain *chain;
   1.128 +	size_t a, w, u;
   1.129 +	int n = 0;
   1.130 +	u = a = w = 0;
   1.131 +
   1.132 +	chain = buf->first;
   1.133 +	/* skip empty at start */
   1.134 +	while (chain && chain->off==0) {
   1.135 +		++n;
   1.136 +		a += chain->buffer_len;
   1.137 +		chain = chain->next;
   1.138 +	}
   1.139 +	/* first nonempty chain: stuff at the end only is wasted. */
   1.140 +	if (chain) {
   1.141 +		++n;
   1.142 +		a += chain->buffer_len;
   1.143 +		u += chain->off;
   1.144 +		if (chain->next && chain->next->off)
   1.145 +			w += (size_t)(chain->buffer_len - (chain->misalign + chain->off));
   1.146 +		chain = chain->next;
   1.147 +	}
   1.148 +	/* subsequent nonempty chains */
   1.149 +	while (chain && chain->off) {
   1.150 +		++n;
   1.151 +		a += chain->buffer_len;
   1.152 +		w += (size_t)chain->misalign;
   1.153 +		u += chain->off;
   1.154 +		if (chain->next && chain->next->off)
   1.155 +			w += (size_t) (chain->buffer_len - (chain->misalign + chain->off));
   1.156 +		chain = chain->next;
   1.157 +	}
   1.158 +	/* subsequent empty chains */
   1.159 +	while (chain) {
   1.160 +		++n;
   1.161 +		a += chain->buffer_len;
   1.162 +	}
   1.163 +	*allocatedp = a;
   1.164 +	*wastedp = w;
   1.165 +	*usedp = u;
   1.166 +}
   1.167 +
   1.168 +#define evbuffer_validate(buf)			\
   1.169 +	TT_STMT_BEGIN if (!_evbuffer_validate(buf)) TT_DIE(("Buffer format invalid")); TT_STMT_END
   1.170 +
   1.171 +static void
   1.172 +test_evbuffer(void *ptr)
   1.173 +{
   1.174 +	static char buffer[512], *tmp;
   1.175 +	struct evbuffer *evb = evbuffer_new();
   1.176 +	struct evbuffer *evb_two = evbuffer_new();
   1.177 +	size_t sz_tmp;
   1.178 +	int i;
   1.179 +
   1.180 +	evbuffer_validate(evb);
   1.181 +	evbuffer_add_printf(evb, "%s/%d", "hello", 1);
   1.182 +	evbuffer_validate(evb);
   1.183 +
   1.184 +	tt_assert(evbuffer_get_length(evb) == 7);
   1.185 +	tt_assert(!memcmp((char*)EVBUFFER_DATA(evb), "hello/1", 1));
   1.186 +
   1.187 +	evbuffer_add_buffer(evb, evb_two);
   1.188 +	evbuffer_validate(evb);
   1.189 +
   1.190 +	evbuffer_drain(evb, strlen("hello/"));
   1.191 +	evbuffer_validate(evb);
   1.192 +	tt_assert(evbuffer_get_length(evb) == 1);
   1.193 +	tt_assert(!memcmp((char*)EVBUFFER_DATA(evb), "1", 1));
   1.194 +
   1.195 +	evbuffer_add_printf(evb_two, "%s", "/hello");
   1.196 +	evbuffer_validate(evb);
   1.197 +	evbuffer_add_buffer(evb, evb_two);
   1.198 +	evbuffer_validate(evb);
   1.199 +
   1.200 +	tt_assert(evbuffer_get_length(evb_two) == 0);
   1.201 +	tt_assert(evbuffer_get_length(evb) == 7);
   1.202 +	tt_assert(!memcmp((char*)EVBUFFER_DATA(evb), "1/hello", 7) != 0);
   1.203 +
   1.204 +	memset(buffer, 0, sizeof(buffer));
   1.205 +	evbuffer_add(evb, buffer, sizeof(buffer));
   1.206 +	evbuffer_validate(evb);
   1.207 +	tt_assert(evbuffer_get_length(evb) == 7 + 512);
   1.208 +
   1.209 +	tmp = (char *)evbuffer_pullup(evb, 7 + 512);
   1.210 +	tt_assert(tmp);
   1.211 +	tt_assert(!strncmp(tmp, "1/hello", 7));
   1.212 +	tt_assert(!memcmp(tmp + 7, buffer, sizeof(buffer)));
   1.213 +	evbuffer_validate(evb);
   1.214 +
   1.215 +	evbuffer_prepend(evb, "something", 9);
   1.216 +	evbuffer_validate(evb);
   1.217 +	evbuffer_prepend(evb, "else", 4);
   1.218 +	evbuffer_validate(evb);
   1.219 +
   1.220 +	tmp = (char *)evbuffer_pullup(evb, 4 + 9 + 7);
   1.221 +	tt_assert(!strncmp(tmp, "elsesomething1/hello", 4 + 9 + 7));
   1.222 +	evbuffer_validate(evb);
   1.223 +
   1.224 +	evbuffer_drain(evb, -1);
   1.225 +	evbuffer_validate(evb);
   1.226 +	evbuffer_drain(evb_two, -1);
   1.227 +	evbuffer_validate(evb);
   1.228 +
   1.229 +	for (i = 0; i < 3; ++i) {
   1.230 +		evbuffer_add(evb_two, buffer, sizeof(buffer));
   1.231 +		evbuffer_validate(evb_two);
   1.232 +		evbuffer_add_buffer(evb, evb_two);
   1.233 +		evbuffer_validate(evb);
   1.234 +		evbuffer_validate(evb_two);
   1.235 +	}
   1.236 +
   1.237 +	tt_assert(evbuffer_get_length(evb_two) == 0);
   1.238 +	tt_assert(evbuffer_get_length(evb) == i * sizeof(buffer));
   1.239 +
   1.240 +	/* test remove buffer */
   1.241 +	sz_tmp = (size_t)(sizeof(buffer)*2.5);
   1.242 +	evbuffer_remove_buffer(evb, evb_two, sz_tmp);
   1.243 +	tt_assert(evbuffer_get_length(evb_two) == sz_tmp);
   1.244 +	tt_assert(evbuffer_get_length(evb) == sizeof(buffer) / 2);
   1.245 +	evbuffer_validate(evb);
   1.246 +
   1.247 +	if (memcmp(evbuffer_pullup(
   1.248 +			   evb, -1), buffer, sizeof(buffer) / 2) != 0 ||
   1.249 +	    memcmp(evbuffer_pullup(
   1.250 +			   evb_two, -1), buffer, sizeof(buffer) != 0))
   1.251 +		tt_abort_msg("Pullup did not preserve content");
   1.252 +
   1.253 +	evbuffer_validate(evb);
   1.254 +
   1.255 +
   1.256 +	/* testing one-vector reserve and commit */
   1.257 +	{
   1.258 +		struct evbuffer_iovec v[1];
   1.259 +		char *buf;
   1.260 +		int i, j, r;
   1.261 +
   1.262 +		for (i = 0; i < 3; ++i) {
   1.263 +			r = evbuffer_reserve_space(evb, 10000, v, 1);
   1.264 +			tt_int_op(r, ==, 1);
   1.265 +			tt_assert(v[0].iov_len >= 10000);
   1.266 +			tt_assert(v[0].iov_base != NULL);
   1.267 +
   1.268 +			evbuffer_validate(evb);
   1.269 +			buf = v[0].iov_base;
   1.270 +			for (j = 0; j < 10000; ++j) {
   1.271 +				buf[j] = j;
   1.272 +			}
   1.273 +			evbuffer_validate(evb);
   1.274 +
   1.275 +			tt_int_op(evbuffer_commit_space(evb, v, 1), ==, 0);
   1.276 +			evbuffer_validate(evb);
   1.277 +
   1.278 +			tt_assert(evbuffer_get_length(evb) >= 10000);
   1.279 +
   1.280 +			evbuffer_drain(evb, j * 5000);
   1.281 +			evbuffer_validate(evb);
   1.282 +		}
   1.283 +	}
   1.284 +
   1.285 + end:
   1.286 +	evbuffer_free(evb);
   1.287 +	evbuffer_free(evb_two);
   1.288 +}
   1.289 +
   1.290 +static void
   1.291 +no_cleanup(const void *data, size_t datalen, void *extra)
   1.292 +{
   1.293 +}
   1.294 +
   1.295 +static void
   1.296 +test_evbuffer_remove_buffer_with_empty(void *ptr)
   1.297 +{
   1.298 +    struct evbuffer *src = evbuffer_new();
   1.299 +    struct evbuffer *dst = evbuffer_new();
   1.300 +    char buf[2];
   1.301 +
   1.302 +    evbuffer_validate(src);
   1.303 +    evbuffer_validate(dst);
   1.304 +
   1.305 +    /* setup the buffers */
   1.306 +    /* we need more data in src than we will move later */
   1.307 +    evbuffer_add_reference(src, buf, sizeof(buf), no_cleanup, NULL);
   1.308 +    evbuffer_add_reference(src, buf, sizeof(buf), no_cleanup, NULL);
   1.309 +    /* we need one buffer in dst and one empty buffer at the end */
   1.310 +    evbuffer_add(dst, buf, sizeof(buf));
   1.311 +    evbuffer_add_reference(dst, buf, 0, no_cleanup, NULL);
   1.312 +
   1.313 +    evbuffer_validate(src);
   1.314 +    evbuffer_validate(dst);
   1.315 +
   1.316 +    /* move three bytes over */
   1.317 +    evbuffer_remove_buffer(src, dst, 3);
   1.318 +
   1.319 +    evbuffer_validate(src);
   1.320 +    evbuffer_validate(dst);
   1.321 +
   1.322 +end:
   1.323 +    evbuffer_free(src);
   1.324 +    evbuffer_free(dst);
   1.325 +}
   1.326 +
   1.327 +static void
   1.328 +test_evbuffer_reserve2(void *ptr)
   1.329 +{
   1.330 +	/* Test the two-vector cases of reserve/commit. */
   1.331 +	struct evbuffer *buf = evbuffer_new();
   1.332 +	int n, i;
   1.333 +	struct evbuffer_iovec v[2];
   1.334 +	size_t remaining;
   1.335 +	char *cp, *cp2;
   1.336 +
   1.337 +	/* First chunk will necessarily be one chunk. Use 512 bytes of it.*/
   1.338 +	n = evbuffer_reserve_space(buf, 1024, v, 2);
   1.339 +	tt_int_op(n, ==, 1);
   1.340 +	tt_int_op(evbuffer_get_length(buf), ==, 0);
   1.341 +	tt_assert(v[0].iov_base != NULL);
   1.342 +	tt_int_op(v[0].iov_len, >=, 1024);
   1.343 +	memset(v[0].iov_base, 'X', 512);
   1.344 +	cp = v[0].iov_base;
   1.345 +	remaining = v[0].iov_len - 512;
   1.346 +	v[0].iov_len = 512;
   1.347 +	evbuffer_validate(buf);
   1.348 +	tt_int_op(0, ==, evbuffer_commit_space(buf, v, 1));
   1.349 +	tt_int_op(evbuffer_get_length(buf), ==, 512);
   1.350 +	evbuffer_validate(buf);
   1.351 +
   1.352 +	/* Ask for another same-chunk request, in an existing chunk. Use 8
   1.353 +	 * bytes of it. */
   1.354 +	n = evbuffer_reserve_space(buf, 32, v, 2);
   1.355 +	tt_int_op(n, ==, 1);
   1.356 +	tt_assert(cp + 512 == v[0].iov_base);
   1.357 +	tt_int_op(remaining, ==, v[0].iov_len);
   1.358 +	memset(v[0].iov_base, 'Y', 8);
   1.359 +	v[0].iov_len = 8;
   1.360 +	tt_int_op(0, ==, evbuffer_commit_space(buf, v, 1));
   1.361 +	tt_int_op(evbuffer_get_length(buf), ==, 520);
   1.362 +	remaining -= 8;
   1.363 +	evbuffer_validate(buf);
   1.364 +
   1.365 +	/* Now ask for a request that will be split. Use only one byte of it,
   1.366 +	   though. */
   1.367 +	n = evbuffer_reserve_space(buf, remaining+64, v, 2);
   1.368 +	tt_int_op(n, ==, 2);
   1.369 +	tt_assert(cp + 520 == v[0].iov_base);
   1.370 +	tt_int_op(remaining, ==, v[0].iov_len);
   1.371 +	tt_assert(v[1].iov_base);
   1.372 +	tt_assert(v[1].iov_len >= 64);
   1.373 +	cp2 = v[1].iov_base;
   1.374 +	memset(v[0].iov_base, 'Z', 1);
   1.375 +	v[0].iov_len = 1;
   1.376 +	tt_int_op(0, ==, evbuffer_commit_space(buf, v, 1));
   1.377 +	tt_int_op(evbuffer_get_length(buf), ==, 521);
   1.378 +	remaining -= 1;
   1.379 +	evbuffer_validate(buf);
   1.380 +
   1.381 +	/* Now ask for a request that will be split. Use some of the first
   1.382 +	 * part and some of the second. */
   1.383 +	n = evbuffer_reserve_space(buf, remaining+64, v, 2);
   1.384 +	evbuffer_validate(buf);
   1.385 +	tt_int_op(n, ==, 2);
   1.386 +	tt_assert(cp + 521 == v[0].iov_base);
   1.387 +	tt_int_op(remaining, ==, v[0].iov_len);
   1.388 +	tt_assert(v[1].iov_base == cp2);
   1.389 +	tt_assert(v[1].iov_len >= 64);
   1.390 +	memset(v[0].iov_base, 'W', 400);
   1.391 +	v[0].iov_len = 400;
   1.392 +	memset(v[1].iov_base, 'x', 60);
   1.393 +	v[1].iov_len = 60;
   1.394 +	tt_int_op(0, ==, evbuffer_commit_space(buf, v, 2));
   1.395 +	tt_int_op(evbuffer_get_length(buf), ==, 981);
   1.396 +	evbuffer_validate(buf);
   1.397 +
   1.398 +	/* Now peek to make sure stuff got made how we like. */
   1.399 +	memset(v,0,sizeof(v));
   1.400 +	n = evbuffer_peek(buf, -1, NULL, v, 2);
   1.401 +	tt_int_op(n, ==, 2);
   1.402 +	tt_int_op(v[0].iov_len, ==, 921);
   1.403 +	tt_int_op(v[1].iov_len, ==, 60);
   1.404 +
   1.405 +	cp = v[0].iov_base;
   1.406 +	for (i=0; i<512; ++i)
   1.407 +		tt_int_op(cp[i], ==, 'X');
   1.408 +	for (i=512; i<520; ++i)
   1.409 +		tt_int_op(cp[i], ==, 'Y');
   1.410 +	for (i=520; i<521; ++i)
   1.411 +		tt_int_op(cp[i], ==, 'Z');
   1.412 +	for (i=521; i<921; ++i)
   1.413 +		tt_int_op(cp[i], ==, 'W');
   1.414 +
   1.415 +	cp = v[1].iov_base;
   1.416 +	for (i=0; i<60; ++i)
   1.417 +		tt_int_op(cp[i], ==, 'x');
   1.418 +
   1.419 +end:
   1.420 +	evbuffer_free(buf);
   1.421 +}
   1.422 +
   1.423 +static void
   1.424 +test_evbuffer_reserve_many(void *ptr)
   1.425 +{
   1.426 +	/* This is a glass-box test to handle expanding a buffer with more
   1.427 +	 * chunks and reallocating chunks as needed */
   1.428 +	struct evbuffer *buf = evbuffer_new();
   1.429 +	struct evbuffer_iovec v[8];
   1.430 +	int n;
   1.431 +	size_t sz;
   1.432 +	int add_data = ptr && !strcmp(ptr, "add");
   1.433 +	int fill_first = ptr && !strcmp(ptr, "fill");
   1.434 +	char *cp1, *cp2;
   1.435 +
   1.436 +	/* When reserving the the first chunk, we just allocate it */
   1.437 +	n = evbuffer_reserve_space(buf, 128, v, 2);
   1.438 +	evbuffer_validate(buf);
   1.439 +	tt_int_op(n, ==, 1);
   1.440 +	tt_assert(v[0].iov_len >= 128);
   1.441 +	sz = v[0].iov_len;
   1.442 +	cp1 = v[0].iov_base;
   1.443 +	if (add_data) {
   1.444 +		*(char*)v[0].iov_base = 'X';
   1.445 +		v[0].iov_len = 1;
   1.446 +		n = evbuffer_commit_space(buf, v, 1);
   1.447 +		tt_int_op(n, ==, 0);
   1.448 +	} else if (fill_first) {
   1.449 +		memset(v[0].iov_base, 'X', v[0].iov_len);
   1.450 +		n = evbuffer_commit_space(buf, v, 1);
   1.451 +		tt_int_op(n, ==, 0);
   1.452 +		n = evbuffer_reserve_space(buf, 128, v, 2);
   1.453 +		tt_int_op(n, ==, 1);
   1.454 +		sz = v[0].iov_len;
   1.455 +		tt_assert(v[0].iov_base != cp1);
   1.456 +		cp1 = v[0].iov_base;
   1.457 +	}
   1.458 +
   1.459 +	/* Make another chunk get added. */
   1.460 +	n = evbuffer_reserve_space(buf, sz+128, v, 2);
   1.461 +	evbuffer_validate(buf);
   1.462 +	tt_int_op(n, ==, 2);
   1.463 +	sz = v[0].iov_len + v[1].iov_len;
   1.464 +	tt_int_op(sz, >=, v[0].iov_len+128);
   1.465 +	if (add_data) {
   1.466 +		tt_assert(v[0].iov_base == cp1 + 1);
   1.467 +	} else {
   1.468 +		tt_assert(v[0].iov_base == cp1);
   1.469 +	}
   1.470 +	cp1 = v[0].iov_base;
   1.471 +	cp2 = v[1].iov_base;
   1.472 +
   1.473 +	/* And a third chunk. */
   1.474 +	n = evbuffer_reserve_space(buf, sz+128, v, 3);
   1.475 +	evbuffer_validate(buf);
   1.476 +	tt_int_op(n, ==, 3);
   1.477 +	tt_assert(cp1 == v[0].iov_base);
   1.478 +	tt_assert(cp2 == v[1].iov_base);
   1.479 +	sz = v[0].iov_len + v[1].iov_len + v[2].iov_len;
   1.480 +
   1.481 +	/* Now force a reallocation by asking for more space in only 2
   1.482 +	 * buffers. */
   1.483 +	n = evbuffer_reserve_space(buf, sz+128, v, 2);
   1.484 +	evbuffer_validate(buf);
   1.485 +	if (add_data) {
   1.486 +		tt_int_op(n, ==, 2);
   1.487 +		tt_assert(cp1 == v[0].iov_base);
   1.488 +	} else {
   1.489 +		tt_int_op(n, ==, 1);
   1.490 +	}
   1.491 +
   1.492 +end:
   1.493 +	evbuffer_free(buf);
   1.494 +}
   1.495 +
   1.496 +static void
   1.497 +test_evbuffer_expand(void *ptr)
   1.498 +{
   1.499 +	char data[4096];
   1.500 +	struct evbuffer *buf;
   1.501 +	size_t a,w,u;
   1.502 +	void *buffer;
   1.503 +
   1.504 +	memset(data, 'X', sizeof(data));
   1.505 +
   1.506 +	/* Make sure that expand() works on an empty buffer */
   1.507 +	buf = evbuffer_new();
   1.508 +	tt_int_op(evbuffer_expand(buf, 20000), ==, 0);
   1.509 +	evbuffer_validate(buf);
   1.510 +	a=w=u=0;
   1.511 +	evbuffer_get_waste(buf, &a,&w,&u);
   1.512 +	tt_assert(w == 0);
   1.513 +	tt_assert(u == 0);
   1.514 +	tt_assert(a >= 20000);
   1.515 +	tt_assert(buf->first);
   1.516 +	tt_assert(buf->first == buf->last);
   1.517 +	tt_assert(buf->first->off == 0);
   1.518 +	tt_assert(buf->first->buffer_len >= 20000);
   1.519 +
   1.520 +	/* Make sure that expand() works as a no-op when there's enough
   1.521 +	 * contiguous space already. */
   1.522 +	buffer = buf->first->buffer;
   1.523 +	evbuffer_add(buf, data, 1024);
   1.524 +	tt_int_op(evbuffer_expand(buf, 1024), ==, 0);
   1.525 +	tt_assert(buf->first->buffer == buffer);
   1.526 +	evbuffer_validate(buf);
   1.527 +	evbuffer_free(buf);
   1.528 +
   1.529 +	/* Make sure that expand() can work by moving misaligned data
   1.530 +	 * when it makes sense to do so. */
   1.531 +	buf = evbuffer_new();
   1.532 +	evbuffer_add(buf, data, 400);
   1.533 +	{
   1.534 +		int n = (int)(buf->first->buffer_len - buf->first->off - 1);
   1.535 +		tt_assert(n < (int)sizeof(data));
   1.536 +		evbuffer_add(buf, data, n);
   1.537 +	}
   1.538 +	tt_assert(buf->first == buf->last);
   1.539 +	tt_assert(buf->first->off == buf->first->buffer_len - 1);
   1.540 +	evbuffer_drain(buf, buf->first->off - 1);
   1.541 +	tt_assert(1 == evbuffer_get_length(buf));
   1.542 +	tt_assert(buf->first->misalign > 0);
   1.543 +	tt_assert(buf->first->off == 1);
   1.544 +	buffer = buf->first->buffer;
   1.545 +	tt_assert(evbuffer_expand(buf, 40) == 0);
   1.546 +	tt_assert(buf->first == buf->last);
   1.547 +	tt_assert(buf->first->off == 1);
   1.548 +	tt_assert(buf->first->buffer == buffer);
   1.549 +	tt_assert(buf->first->misalign == 0);
   1.550 +	evbuffer_validate(buf);
   1.551 +	evbuffer_free(buf);
   1.552 +
   1.553 +	/* add, expand, pull-up: This used to crash libevent. */
   1.554 +	buf = evbuffer_new();
   1.555 +
   1.556 +	evbuffer_add(buf, data, sizeof(data));
   1.557 +	evbuffer_add(buf, data, sizeof(data));
   1.558 +	evbuffer_add(buf, data, sizeof(data));
   1.559 +
   1.560 +	evbuffer_validate(buf);
   1.561 +	evbuffer_expand(buf, 1024);
   1.562 +	evbuffer_validate(buf);
   1.563 +	evbuffer_pullup(buf, -1);
   1.564 +	evbuffer_validate(buf);
   1.565 +
   1.566 +end:
   1.567 +	evbuffer_free(buf);
   1.568 +}
   1.569 +
   1.570 +
   1.571 +static int reference_cb_called;
   1.572 +static void
   1.573 +reference_cb(const void *data, size_t len, void *extra)
   1.574 +{
   1.575 +	tt_str_op(data, ==, "this is what we add as read-only memory.");
   1.576 +	tt_int_op(len, ==, strlen(data));
   1.577 +	tt_want(extra == (void *)0xdeadaffe);
   1.578 +	++reference_cb_called;
   1.579 +end:
   1.580 +	;
   1.581 +}
   1.582 +
   1.583 +static void
   1.584 +test_evbuffer_reference(void *ptr)
   1.585 +{
   1.586 +	struct evbuffer *src = evbuffer_new();
   1.587 +	struct evbuffer *dst = evbuffer_new();
   1.588 +	struct evbuffer_iovec v[1];
   1.589 +	const char *data = "this is what we add as read-only memory.";
   1.590 +	reference_cb_called = 0;
   1.591 +
   1.592 +	tt_assert(evbuffer_add_reference(src, data, strlen(data),
   1.593 +		 reference_cb, (void *)0xdeadaffe) != -1);
   1.594 +
   1.595 +	evbuffer_reserve_space(dst, strlen(data), v, 1);
   1.596 +	tt_assert(evbuffer_remove(src, v[0].iov_base, 10) != -1);
   1.597 +
   1.598 +	evbuffer_validate(src);
   1.599 +	evbuffer_validate(dst);
   1.600 +
   1.601 +	/* make sure that we don't write data at the beginning */
   1.602 +	evbuffer_prepend(src, "aaaaa", 5);
   1.603 +	evbuffer_validate(src);
   1.604 +	evbuffer_drain(src, 5);
   1.605 +
   1.606 +	tt_assert(evbuffer_remove(src, ((char*)(v[0].iov_base)) + 10,
   1.607 +		strlen(data) - 10) != -1);
   1.608 +
   1.609 +	v[0].iov_len = strlen(data);
   1.610 +
   1.611 +	evbuffer_commit_space(dst, v, 1);
   1.612 +	evbuffer_validate(src);
   1.613 +	evbuffer_validate(dst);
   1.614 +
   1.615 +	tt_int_op(reference_cb_called, ==, 1);
   1.616 +
   1.617 +	tt_assert(!memcmp(evbuffer_pullup(dst, strlen(data)),
   1.618 +			  data, strlen(data)));
   1.619 +	evbuffer_validate(dst);
   1.620 +
   1.621 + end:
   1.622 +	evbuffer_free(dst);
   1.623 +	evbuffer_free(src);
   1.624 +}
   1.625 +
   1.626 +int _evbuffer_testing_use_sendfile(void);
   1.627 +int _evbuffer_testing_use_mmap(void);
   1.628 +int _evbuffer_testing_use_linear_file_access(void);
   1.629 +
   1.630 +static void
   1.631 +test_evbuffer_add_file(void *ptr)
   1.632 +{
   1.633 +	const char *impl = ptr;
   1.634 +	struct evbuffer *src = evbuffer_new();
   1.635 +	const char *data = "this is what we add as file system data.";
   1.636 +	size_t datalen;
   1.637 +	const char *compare;
   1.638 +	int fd = -1;
   1.639 +	evutil_socket_t pair[2] = {-1, -1};
   1.640 +	int r=0, n_written=0;
   1.641 +
   1.642 +	/* Add a test for a big file. XXXX */
   1.643 +
   1.644 +	tt_assert(impl);
   1.645 +	if (!strcmp(impl, "sendfile")) {
   1.646 +		if (!_evbuffer_testing_use_sendfile())
   1.647 +			tt_skip();
   1.648 +		TT_BLATHER(("Using sendfile-based implementaion"));
   1.649 +	} else if (!strcmp(impl, "mmap")) {
   1.650 +		if (!_evbuffer_testing_use_mmap())
   1.651 +			tt_skip();
   1.652 +		TT_BLATHER(("Using mmap-based implementaion"));
   1.653 +	} else if (!strcmp(impl, "linear")) {
   1.654 +		if (!_evbuffer_testing_use_linear_file_access())
   1.655 +			tt_skip();
   1.656 +		TT_BLATHER(("Using read-based implementaion"));
   1.657 +	} else {
   1.658 +		TT_DIE(("Didn't recognize the implementation"));
   1.659 +	}
   1.660 +
   1.661 +	/* Say that it drains to a fd so that we can use sendfile. */
   1.662 +	evbuffer_set_flags(src, EVBUFFER_FLAG_DRAINS_TO_FD);
   1.663 +
   1.664 +#if defined(_EVENT_HAVE_SENDFILE) && defined(__sun__) && defined(__svr4__)
   1.665 +	/* We need to use a pair of AF_INET sockets, since Solaris
   1.666 +	   doesn't support sendfile() over AF_UNIX. */
   1.667 +	if (evutil_ersatz_socketpair(AF_INET, SOCK_STREAM, 0, pair) == -1)
   1.668 +		tt_abort_msg("ersatz_socketpair failed");
   1.669 +#else
   1.670 +	if (evutil_socketpair(AF_UNIX, SOCK_STREAM, 0, pair) == -1)
   1.671 +		tt_abort_msg("socketpair failed");
   1.672 +#endif
   1.673 +
   1.674 +	datalen = strlen(data);
   1.675 +	fd = regress_make_tmpfile(data, datalen);
   1.676 +
   1.677 +	tt_assert(fd != -1);
   1.678 +
   1.679 +	tt_assert(evbuffer_add_file(src, fd, 0, datalen) != -1);
   1.680 +
   1.681 +	evbuffer_validate(src);
   1.682 +
   1.683 +	while (evbuffer_get_length(src) &&
   1.684 +	    (r = evbuffer_write(src, pair[0])) > 0) {
   1.685 +		evbuffer_validate(src);
   1.686 +		n_written += r;
   1.687 +	}
   1.688 +	tt_int_op(r, !=, -1);
   1.689 +	tt_int_op(n_written, ==, datalen);
   1.690 +
   1.691 +	evbuffer_validate(src);
   1.692 +	tt_int_op(evbuffer_read(src, pair[1], (int)strlen(data)), ==, datalen);
   1.693 +	evbuffer_validate(src);
   1.694 +	compare = (char *)evbuffer_pullup(src, datalen);
   1.695 +	tt_assert(compare != NULL);
   1.696 +	if (memcmp(compare, data, datalen))
   1.697 +		tt_abort_msg("Data from add_file differs.");
   1.698 +
   1.699 +	evbuffer_validate(src);
   1.700 + end:
   1.701 +	if (pair[0] >= 0)
   1.702 +		evutil_closesocket(pair[0]);
   1.703 +	if (pair[1] >= 0)
   1.704 +		evutil_closesocket(pair[1]);
   1.705 +	evbuffer_free(src);
   1.706 +}
   1.707 +
   1.708 +#ifndef _EVENT_DISABLE_MM_REPLACEMENT
   1.709 +static void *
   1.710 +failing_malloc(size_t how_much)
   1.711 +{
   1.712 +	errno = ENOMEM;
   1.713 +	return NULL;
   1.714 +}
   1.715 +#endif
   1.716 +
   1.717 +static void
   1.718 +test_evbuffer_readln(void *ptr)
   1.719 +{
   1.720 +	struct evbuffer *evb = evbuffer_new();
   1.721 +	struct evbuffer *evb_tmp = evbuffer_new();
   1.722 +	const char *s;
   1.723 +	char *cp = NULL;
   1.724 +	size_t sz;
   1.725 +
   1.726 +#define tt_line_eq(content)						\
   1.727 +	TT_STMT_BEGIN							\
   1.728 +	if (!cp || sz != strlen(content) || strcmp(cp, content)) {	\
   1.729 +		TT_DIE(("Wanted %s; got %s [%d]", content, cp, (int)sz)); \
   1.730 +	}								\
   1.731 +	TT_STMT_END
   1.732 +
   1.733 +	/* Test EOL_ANY. */
   1.734 +	s = "complex silly newline\r\n\n\r\n\n\rmore\0\n";
   1.735 +	evbuffer_add(evb, s, strlen(s)+2);
   1.736 +	evbuffer_validate(evb);
   1.737 +	cp = evbuffer_readln(evb, &sz, EVBUFFER_EOL_ANY);
   1.738 +	tt_line_eq("complex silly newline");
   1.739 +	free(cp);
   1.740 +	evbuffer_validate(evb);
   1.741 +	cp = evbuffer_readln(evb, &sz, EVBUFFER_EOL_ANY);
   1.742 +	if (!cp || sz != 5 || memcmp(cp, "more\0\0", 6))
   1.743 +		tt_abort_msg("Not as expected");
   1.744 +	tt_uint_op(evbuffer_get_length(evb), ==, 0);
   1.745 +	evbuffer_validate(evb);
   1.746 +	s = "\nno newline";
   1.747 +	evbuffer_add(evb, s, strlen(s));
   1.748 +	free(cp);
   1.749 +	evbuffer_validate(evb);
   1.750 +	cp = evbuffer_readln(evb, &sz, EVBUFFER_EOL_ANY);
   1.751 +	tt_line_eq("");
   1.752 +	free(cp);
   1.753 +	evbuffer_validate(evb);
   1.754 +	cp = evbuffer_readln(evb, &sz, EVBUFFER_EOL_ANY);
   1.755 +	tt_assert(!cp);
   1.756 +	evbuffer_validate(evb);
   1.757 +	evbuffer_drain(evb, evbuffer_get_length(evb));
   1.758 +	tt_assert(evbuffer_get_length(evb) == 0);
   1.759 +	evbuffer_validate(evb);
   1.760 +
   1.761 +	/* Test EOL_CRLF */
   1.762 +	s = "Line with\rin the middle\nLine with good crlf\r\n\nfinal\n";
   1.763 +	evbuffer_add(evb, s, strlen(s));
   1.764 +	evbuffer_validate(evb);
   1.765 +	cp = evbuffer_readln(evb, &sz, EVBUFFER_EOL_CRLF);
   1.766 +	tt_line_eq("Line with\rin the middle");
   1.767 +	free(cp);
   1.768 +	evbuffer_validate(evb);
   1.769 +
   1.770 +	cp = evbuffer_readln(evb, &sz, EVBUFFER_EOL_CRLF);
   1.771 +	tt_line_eq("Line with good crlf");
   1.772 +	free(cp);
   1.773 +	evbuffer_validate(evb);
   1.774 +
   1.775 +	cp = evbuffer_readln(evb, &sz, EVBUFFER_EOL_CRLF);
   1.776 +	tt_line_eq("");
   1.777 +	free(cp);
   1.778 +	evbuffer_validate(evb);
   1.779 +
   1.780 +	cp = evbuffer_readln(evb, &sz, EVBUFFER_EOL_CRLF);
   1.781 +	tt_line_eq("final");
   1.782 +	s = "x";
   1.783 +	evbuffer_validate(evb);
   1.784 +	evbuffer_add(evb, s, 1);
   1.785 +	evbuffer_validate(evb);
   1.786 +	free(cp);
   1.787 +	cp = evbuffer_readln(evb, &sz, EVBUFFER_EOL_CRLF);
   1.788 +	tt_assert(!cp);
   1.789 +	evbuffer_validate(evb);
   1.790 +
   1.791 +	/* Test CRLF_STRICT */
   1.792 +	s = " and a bad crlf\nand a good one\r\n\r\nMore\r";
   1.793 +	evbuffer_add(evb, s, strlen(s));
   1.794 +	evbuffer_validate(evb);
   1.795 +	cp = evbuffer_readln(evb, &sz, EVBUFFER_EOL_CRLF_STRICT);
   1.796 +	tt_line_eq("x and a bad crlf\nand a good one");
   1.797 +	free(cp);
   1.798 +	evbuffer_validate(evb);
   1.799 +
   1.800 +	cp = evbuffer_readln(evb, &sz, EVBUFFER_EOL_CRLF_STRICT);
   1.801 +	tt_line_eq("");
   1.802 +	free(cp);
   1.803 +	evbuffer_validate(evb);
   1.804 +
   1.805 +	cp = evbuffer_readln(evb, &sz, EVBUFFER_EOL_CRLF_STRICT);
   1.806 +	tt_assert(!cp);
   1.807 +	evbuffer_validate(evb);
   1.808 +	evbuffer_add(evb, "\n", 1);
   1.809 +	evbuffer_validate(evb);
   1.810 +
   1.811 +	cp = evbuffer_readln(evb, &sz, EVBUFFER_EOL_CRLF_STRICT);
   1.812 +	tt_line_eq("More");
   1.813 +	free(cp);
   1.814 +	tt_assert(evbuffer_get_length(evb) == 0);
   1.815 +	evbuffer_validate(evb);
   1.816 +
   1.817 +	s = "An internal CR\r is not an eol\r\nNor is a lack of one";
   1.818 +	evbuffer_add(evb, s, strlen(s));
   1.819 +	cp = evbuffer_readln(evb, &sz, EVBUFFER_EOL_CRLF_STRICT);
   1.820 +	tt_line_eq("An internal CR\r is not an eol");
   1.821 +	free(cp);
   1.822 +	evbuffer_validate(evb);
   1.823 +
   1.824 +	cp = evbuffer_readln(evb, &sz, EVBUFFER_EOL_CRLF_STRICT);
   1.825 +	tt_assert(!cp);
   1.826 +	evbuffer_validate(evb);
   1.827 +
   1.828 +	evbuffer_add(evb, "\r\n", 2);
   1.829 +	evbuffer_validate(evb);
   1.830 +	cp = evbuffer_readln(evb, &sz, EVBUFFER_EOL_CRLF_STRICT);
   1.831 +	tt_line_eq("Nor is a lack of one");
   1.832 +	free(cp);
   1.833 +	tt_assert(evbuffer_get_length(evb) == 0);
   1.834 +	evbuffer_validate(evb);
   1.835 +
   1.836 +	/* Test LF */
   1.837 +	s = "An\rand a nl\n\nText";
   1.838 +	evbuffer_add(evb, s, strlen(s));
   1.839 +	evbuffer_validate(evb);
   1.840 +
   1.841 +	cp = evbuffer_readln(evb, &sz, EVBUFFER_EOL_LF);
   1.842 +	tt_line_eq("An\rand a nl");
   1.843 +	free(cp);
   1.844 +	evbuffer_validate(evb);
   1.845 +
   1.846 +	cp = evbuffer_readln(evb, &sz, EVBUFFER_EOL_LF);
   1.847 +	tt_line_eq("");
   1.848 +	free(cp);
   1.849 +	evbuffer_validate(evb);
   1.850 +
   1.851 +	cp = evbuffer_readln(evb, &sz, EVBUFFER_EOL_LF);
   1.852 +	tt_assert(!cp);
   1.853 +	free(cp);
   1.854 +	evbuffer_add(evb, "\n", 1);
   1.855 +	evbuffer_validate(evb);
   1.856 +	cp = evbuffer_readln(evb, &sz, EVBUFFER_EOL_LF);
   1.857 +	tt_line_eq("Text");
   1.858 +	free(cp);
   1.859 +	evbuffer_validate(evb);
   1.860 +
   1.861 +	/* Test CRLF_STRICT - across boundaries*/
   1.862 +	s = " and a bad crlf\nand a good one\r";
   1.863 +	evbuffer_add(evb_tmp, s, strlen(s));
   1.864 +	evbuffer_validate(evb);
   1.865 +	evbuffer_add_buffer(evb, evb_tmp);
   1.866 +	evbuffer_validate(evb);
   1.867 +	s = "\n\r";
   1.868 +	evbuffer_add(evb_tmp, s, strlen(s));
   1.869 +	evbuffer_validate(evb);
   1.870 +	evbuffer_add_buffer(evb, evb_tmp);
   1.871 +	evbuffer_validate(evb);
   1.872 +	s = "\nMore\r";
   1.873 +	evbuffer_add(evb_tmp, s, strlen(s));
   1.874 +	evbuffer_validate(evb);
   1.875 +	evbuffer_add_buffer(evb, evb_tmp);
   1.876 +	evbuffer_validate(evb);
   1.877 +
   1.878 +	cp = evbuffer_readln(evb, &sz, EVBUFFER_EOL_CRLF_STRICT);
   1.879 +	tt_line_eq(" and a bad crlf\nand a good one");
   1.880 +	free(cp);
   1.881 +	evbuffer_validate(evb);
   1.882 +
   1.883 +	cp = evbuffer_readln(evb, &sz, EVBUFFER_EOL_CRLF_STRICT);
   1.884 +	tt_line_eq("");
   1.885 +	free(cp);
   1.886 +	evbuffer_validate(evb);
   1.887 +
   1.888 +	cp = evbuffer_readln(evb, &sz, EVBUFFER_EOL_CRLF_STRICT);
   1.889 +	tt_assert(!cp);
   1.890 +	free(cp);
   1.891 +	evbuffer_validate(evb);
   1.892 +	evbuffer_add(evb, "\n", 1);
   1.893 +	evbuffer_validate(evb);
   1.894 +	cp = evbuffer_readln(evb, &sz, EVBUFFER_EOL_CRLF_STRICT);
   1.895 +	tt_line_eq("More");
   1.896 +	free(cp); cp = NULL;
   1.897 +	evbuffer_validate(evb);
   1.898 +	tt_assert(evbuffer_get_length(evb) == 0);
   1.899 +
   1.900 +	/* Test memory problem*/
   1.901 +	s = "one line\ntwo line\nblue line";
   1.902 +	evbuffer_add(evb_tmp, s, strlen(s));
   1.903 +	evbuffer_validate(evb);
   1.904 +	evbuffer_add_buffer(evb, evb_tmp);
   1.905 +	evbuffer_validate(evb);
   1.906 +
   1.907 +	cp = evbuffer_readln(evb, &sz, EVBUFFER_EOL_LF);
   1.908 +	tt_line_eq("one line");
   1.909 +	free(cp); cp = NULL;
   1.910 +	evbuffer_validate(evb);
   1.911 +
   1.912 +	/* the next call to readline should fail */
   1.913 +#ifndef _EVENT_DISABLE_MM_REPLACEMENT
   1.914 +	event_set_mem_functions(failing_malloc, realloc, free);
   1.915 +	cp = evbuffer_readln(evb, &sz, EVBUFFER_EOL_LF);
   1.916 +	tt_assert(cp == NULL);
   1.917 +	evbuffer_validate(evb);
   1.918 +
   1.919 +	/* now we should get the next line back */
   1.920 +	event_set_mem_functions(malloc, realloc, free);
   1.921 +#endif
   1.922 +	cp = evbuffer_readln(evb, &sz, EVBUFFER_EOL_LF);
   1.923 +	tt_line_eq("two line");
   1.924 +	free(cp); cp = NULL;
   1.925 +	evbuffer_validate(evb);
   1.926 +
   1.927 + end:
   1.928 +	evbuffer_free(evb);
   1.929 +	evbuffer_free(evb_tmp);
   1.930 +	if (cp) free(cp);
   1.931 +}
   1.932 +
   1.933 +static void
   1.934 +test_evbuffer_search_eol(void *ptr)
   1.935 +{
   1.936 +	struct evbuffer *buf = evbuffer_new();
   1.937 +	struct evbuffer_ptr ptr1, ptr2;
   1.938 +	const char *s;
   1.939 +	size_t eol_len;
   1.940 +
   1.941 +	s = "string! \r\n\r\nx\n";
   1.942 +	evbuffer_add(buf, s, strlen(s));
   1.943 +	eol_len = -1;
   1.944 +	ptr1 = evbuffer_search_eol(buf, NULL, &eol_len, EVBUFFER_EOL_CRLF);
   1.945 +	tt_int_op(ptr1.pos, ==, 8);
   1.946 +	tt_int_op(eol_len, ==, 2);
   1.947 +
   1.948 +	eol_len = -1;
   1.949 +	ptr2 = evbuffer_search_eol(buf, &ptr1, &eol_len, EVBUFFER_EOL_CRLF);
   1.950 +	tt_int_op(ptr2.pos, ==, 8);
   1.951 +	tt_int_op(eol_len, ==, 2);
   1.952 +
   1.953 +	evbuffer_ptr_set(buf, &ptr1, 1, EVBUFFER_PTR_ADD);
   1.954 +	eol_len = -1;
   1.955 +	ptr2 = evbuffer_search_eol(buf, &ptr1, &eol_len, EVBUFFER_EOL_CRLF);
   1.956 +	tt_int_op(ptr2.pos, ==, 9);
   1.957 +	tt_int_op(eol_len, ==, 1);
   1.958 +
   1.959 +	eol_len = -1;
   1.960 +	ptr2 = evbuffer_search_eol(buf, &ptr1, &eol_len, EVBUFFER_EOL_CRLF_STRICT);
   1.961 +	tt_int_op(ptr2.pos, ==, 10);
   1.962 +	tt_int_op(eol_len, ==, 2);
   1.963 +
   1.964 +	eol_len = -1;
   1.965 +	ptr1 = evbuffer_search_eol(buf, NULL, &eol_len, EVBUFFER_EOL_LF);
   1.966 +	tt_int_op(ptr1.pos, ==, 9);
   1.967 +	tt_int_op(eol_len, ==, 1);
   1.968 +
   1.969 +	eol_len = -1;
   1.970 +	ptr2 = evbuffer_search_eol(buf, &ptr1, &eol_len, EVBUFFER_EOL_LF);
   1.971 +	tt_int_op(ptr2.pos, ==, 9);
   1.972 +	tt_int_op(eol_len, ==, 1);
   1.973 +
   1.974 +	evbuffer_ptr_set(buf, &ptr1, 1, EVBUFFER_PTR_ADD);
   1.975 +	eol_len = -1;
   1.976 +	ptr2 = evbuffer_search_eol(buf, &ptr1, &eol_len, EVBUFFER_EOL_LF);
   1.977 +	tt_int_op(ptr2.pos, ==, 11);
   1.978 +	tt_int_op(eol_len, ==, 1);
   1.979 +
   1.980 +end:
   1.981 +	evbuffer_free(buf);
   1.982 +}
   1.983 +
   1.984 +static void
   1.985 +test_evbuffer_iterative(void *ptr)
   1.986 +{
   1.987 +	struct evbuffer *buf = evbuffer_new();
   1.988 +	const char *abc = "abcdefghijklmnopqrstvuwxyzabcdefghijklmnopqrstvuwxyzabcdefghijklmnopqrstvuwxyzabcdefghijklmnopqrstvuwxyz";
   1.989 +	unsigned i, j, sum, n;
   1.990 +
   1.991 +	sum = 0;
   1.992 +	n = 0;
   1.993 +	for (i = 0; i < 1000; ++i) {
   1.994 +		for (j = 1; j < strlen(abc); ++j) {
   1.995 +			char format[32];
   1.996 +			evutil_snprintf(format, sizeof(format), "%%%u.%us", j, j);
   1.997 +			evbuffer_add_printf(buf, format, abc);
   1.998 +
   1.999 +			/* Only check for rep violations every so often.
  1.1000 +			   Walking over the whole list of chains can get
  1.1001 +			   pretty expensive as it gets long.
  1.1002 +			 */
  1.1003 +			if ((n % 337) == 0)
  1.1004 +				evbuffer_validate(buf);
  1.1005 +
  1.1006 +			sum += j;
  1.1007 +			n++;
  1.1008 +		}
  1.1009 +	}
  1.1010 +	evbuffer_validate(buf);
  1.1011 +
  1.1012 +	tt_uint_op(sum, ==, evbuffer_get_length(buf));
  1.1013 +
  1.1014 +	{
  1.1015 +		size_t a,w,u;
  1.1016 +		a=w=u=0;
  1.1017 +		evbuffer_get_waste(buf, &a, &w, &u);
  1.1018 +		if (0)
  1.1019 +			printf("Allocated: %u.\nWasted: %u.\nUsed: %u.",
  1.1020 +			    (unsigned)a, (unsigned)w, (unsigned)u);
  1.1021 +		tt_assert( ((double)w)/a < .125);
  1.1022 +	}
  1.1023 + end:
  1.1024 +	evbuffer_free(buf);
  1.1025 +
  1.1026 +}
  1.1027 +
  1.1028 +static void
  1.1029 +test_evbuffer_find(void *ptr)
  1.1030 +{
  1.1031 +	u_char* p;
  1.1032 +	const char* test1 = "1234567890\r\n";
  1.1033 +	const char* test2 = "1234567890\r";
  1.1034 +#define EVBUFFER_INITIAL_LENGTH 256
  1.1035 +	char test3[EVBUFFER_INITIAL_LENGTH];
  1.1036 +	unsigned int i;
  1.1037 +	struct evbuffer * buf = evbuffer_new();
  1.1038 +
  1.1039 +	tt_assert(buf);
  1.1040 +
  1.1041 +	/* make sure evbuffer_find doesn't match past the end of the buffer */
  1.1042 +	evbuffer_add(buf, (u_char*)test1, strlen(test1));
  1.1043 +	evbuffer_validate(buf);
  1.1044 +	evbuffer_drain(buf, strlen(test1));
  1.1045 +	evbuffer_validate(buf);
  1.1046 +	evbuffer_add(buf, (u_char*)test2, strlen(test2));
  1.1047 +	evbuffer_validate(buf);
  1.1048 +	p = evbuffer_find(buf, (u_char*)"\r\n", 2);
  1.1049 +	tt_want(p == NULL);
  1.1050 +
  1.1051 +	/*
  1.1052 +	 * drain the buffer and do another find; in r309 this would
  1.1053 +	 * read past the allocated buffer causing a valgrind error.
  1.1054 +	 */
  1.1055 +	evbuffer_drain(buf, strlen(test2));
  1.1056 +	evbuffer_validate(buf);
  1.1057 +	for (i = 0; i < EVBUFFER_INITIAL_LENGTH; ++i)
  1.1058 +		test3[i] = 'a';
  1.1059 +	test3[EVBUFFER_INITIAL_LENGTH - 1] = 'x';
  1.1060 +	evbuffer_add(buf, (u_char *)test3, EVBUFFER_INITIAL_LENGTH);
  1.1061 +	evbuffer_validate(buf);
  1.1062 +	p = evbuffer_find(buf, (u_char *)"xy", 2);
  1.1063 +	tt_want(p == NULL);
  1.1064 +
  1.1065 +	/* simple test for match at end of allocated buffer */
  1.1066 +	p = evbuffer_find(buf, (u_char *)"ax", 2);
  1.1067 +	tt_assert(p != NULL);
  1.1068 +	tt_want(strncmp((char*)p, "ax", 2) == 0);
  1.1069 +
  1.1070 +end:
  1.1071 +	if (buf)
  1.1072 +		evbuffer_free(buf);
  1.1073 +}
  1.1074 +
  1.1075 +static void
  1.1076 +test_evbuffer_ptr_set(void *ptr)
  1.1077 +{
  1.1078 +	struct evbuffer *buf = evbuffer_new();
  1.1079 +	struct evbuffer_ptr pos;
  1.1080 +	struct evbuffer_iovec v[1];
  1.1081 +
  1.1082 +	tt_assert(buf);
  1.1083 +
  1.1084 +	/* create some chains */
  1.1085 +	evbuffer_reserve_space(buf, 5000, v, 1);
  1.1086 +	v[0].iov_len = 5000;
  1.1087 +	memset(v[0].iov_base, 1, v[0].iov_len);
  1.1088 +	evbuffer_commit_space(buf, v, 1);
  1.1089 +	evbuffer_validate(buf);
  1.1090 +
  1.1091 +	evbuffer_reserve_space(buf, 4000, v, 1);
  1.1092 +	v[0].iov_len = 4000;
  1.1093 +	memset(v[0].iov_base, 2, v[0].iov_len);
  1.1094 +	evbuffer_commit_space(buf, v, 1);
  1.1095 +
  1.1096 +	evbuffer_reserve_space(buf, 3000, v, 1);
  1.1097 +	v[0].iov_len = 3000;
  1.1098 +	memset(v[0].iov_base, 3, v[0].iov_len);
  1.1099 +	evbuffer_commit_space(buf, v, 1);
  1.1100 +	evbuffer_validate(buf);
  1.1101 +
  1.1102 +	tt_int_op(evbuffer_get_length(buf), ==, 12000);
  1.1103 +
  1.1104 +	tt_assert(evbuffer_ptr_set(buf, &pos, 13000, EVBUFFER_PTR_SET) == -1);
  1.1105 +	tt_assert(pos.pos == -1);
  1.1106 +	tt_assert(evbuffer_ptr_set(buf, &pos, 0, EVBUFFER_PTR_SET) == 0);
  1.1107 +	tt_assert(pos.pos == 0);
  1.1108 +	tt_assert(evbuffer_ptr_set(buf, &pos, 13000, EVBUFFER_PTR_ADD) == -1);
  1.1109 +
  1.1110 +	tt_assert(evbuffer_ptr_set(buf, &pos, 0, EVBUFFER_PTR_SET) == 0);
  1.1111 +	tt_assert(pos.pos == 0);
  1.1112 +	tt_assert(evbuffer_ptr_set(buf, &pos, 10000, EVBUFFER_PTR_ADD) == 0);
  1.1113 +	tt_assert(pos.pos == 10000);
  1.1114 +	tt_assert(evbuffer_ptr_set(buf, &pos, 1000, EVBUFFER_PTR_ADD) == 0);
  1.1115 +	tt_assert(pos.pos == 11000);
  1.1116 +	tt_assert(evbuffer_ptr_set(buf, &pos, 1000, EVBUFFER_PTR_ADD) == -1);
  1.1117 +	tt_assert(pos.pos == -1);
  1.1118 +
  1.1119 +end:
  1.1120 +	if (buf)
  1.1121 +		evbuffer_free(buf);
  1.1122 +}
  1.1123 +
  1.1124 +static void
  1.1125 +test_evbuffer_search(void *ptr)
  1.1126 +{
  1.1127 +	struct evbuffer *buf = evbuffer_new();
  1.1128 +	struct evbuffer *tmp = evbuffer_new();
  1.1129 +	struct evbuffer_ptr pos, end;
  1.1130 +
  1.1131 +	tt_assert(buf);
  1.1132 +	tt_assert(tmp);
  1.1133 +
  1.1134 +	/* set up our chains */
  1.1135 +	evbuffer_add_printf(tmp, "hello");  /* 5 chars */
  1.1136 +	evbuffer_add_buffer(buf, tmp);
  1.1137 +	evbuffer_add_printf(tmp, "foo");    /* 3 chars */
  1.1138 +	evbuffer_add_buffer(buf, tmp);
  1.1139 +	evbuffer_add_printf(tmp, "cat");    /* 3 chars */
  1.1140 +	evbuffer_add_buffer(buf, tmp);
  1.1141 +	evbuffer_add_printf(tmp, "attack");
  1.1142 +	evbuffer_add_buffer(buf, tmp);
  1.1143 +
  1.1144 +	pos = evbuffer_search(buf, "attack", 6, NULL);
  1.1145 +	tt_int_op(pos.pos, ==, 11);
  1.1146 +	pos = evbuffer_search(buf, "attacker", 8, NULL);
  1.1147 +	tt_int_op(pos.pos, ==, -1);
  1.1148 +
  1.1149 +	/* test continuing search */
  1.1150 +	pos = evbuffer_search(buf, "oc", 2, NULL);
  1.1151 +	tt_int_op(pos.pos, ==, 7);
  1.1152 +	pos = evbuffer_search(buf, "cat", 3, &pos);
  1.1153 +	tt_int_op(pos.pos, ==, 8);
  1.1154 +	pos = evbuffer_search(buf, "tacking", 7, &pos);
  1.1155 +	tt_int_op(pos.pos, ==, -1);
  1.1156 +
  1.1157 +	evbuffer_ptr_set(buf, &pos, 5, EVBUFFER_PTR_SET);
  1.1158 +	pos = evbuffer_search(buf, "foo", 3, &pos);
  1.1159 +	tt_int_op(pos.pos, ==, 5);
  1.1160 +
  1.1161 +	evbuffer_ptr_set(buf, &pos, 2, EVBUFFER_PTR_ADD);
  1.1162 +	pos = evbuffer_search(buf, "tat", 3, &pos);
  1.1163 +	tt_int_op(pos.pos, ==, 10);
  1.1164 +
  1.1165 +	/* test bounded search. */
  1.1166 +	/* Set "end" to the first t in "attack". */
  1.1167 +	evbuffer_ptr_set(buf, &end, 12, EVBUFFER_PTR_SET);
  1.1168 +	pos = evbuffer_search_range(buf, "foo", 3, NULL, &end);
  1.1169 +	tt_int_op(pos.pos, ==, 5);
  1.1170 +	pos = evbuffer_search_range(buf, "foocata", 7, NULL, &end);
  1.1171 +	tt_int_op(pos.pos, ==, 5);
  1.1172 +	pos = evbuffer_search_range(buf, "foocatat", 8, NULL, &end);
  1.1173 +	tt_int_op(pos.pos, ==, -1);
  1.1174 +	pos = evbuffer_search_range(buf, "ack", 3, NULL, &end);
  1.1175 +	tt_int_op(pos.pos, ==, -1);
  1.1176 +
  1.1177 +
  1.1178 +end:
  1.1179 +	if (buf)
  1.1180 +		evbuffer_free(buf);
  1.1181 +	if (tmp)
  1.1182 +		evbuffer_free(tmp);
  1.1183 +}
  1.1184 +
  1.1185 +static void
  1.1186 +log_change_callback(struct evbuffer *buffer,
  1.1187 +    const struct evbuffer_cb_info *cbinfo,
  1.1188 +    void *arg)
  1.1189 +{
  1.1190 +
  1.1191 +	size_t old_len = cbinfo->orig_size;
  1.1192 +	size_t new_len = old_len + cbinfo->n_added - cbinfo->n_deleted;
  1.1193 +	struct evbuffer *out = arg;
  1.1194 +	evbuffer_add_printf(out, "%lu->%lu; ", (unsigned long)old_len,
  1.1195 +			    (unsigned long)new_len);
  1.1196 +}
  1.1197 +static void
  1.1198 +self_draining_callback(struct evbuffer *evbuffer, size_t old_len,
  1.1199 +		size_t new_len, void *arg)
  1.1200 +{
  1.1201 +	if (new_len > old_len)
  1.1202 +		evbuffer_drain(evbuffer, new_len);
  1.1203 +}
  1.1204 +
  1.1205 +static void
  1.1206 +test_evbuffer_callbacks(void *ptr)
  1.1207 +{
  1.1208 +	struct evbuffer *buf = evbuffer_new();
  1.1209 +	struct evbuffer *buf_out1 = evbuffer_new();
  1.1210 +	struct evbuffer *buf_out2 = evbuffer_new();
  1.1211 +	struct evbuffer_cb_entry *cb1, *cb2;
  1.1212 +
  1.1213 +	tt_assert(buf);
  1.1214 +	tt_assert(buf_out1);
  1.1215 +	tt_assert(buf_out2);
  1.1216 +
  1.1217 +	cb1 = evbuffer_add_cb(buf, log_change_callback, buf_out1);
  1.1218 +	cb2 = evbuffer_add_cb(buf, log_change_callback, buf_out2);
  1.1219 +
  1.1220 +	/* Let's run through adding and deleting some stuff from the buffer
  1.1221 +	 * and turning the callbacks on and off and removing them.  The callback
  1.1222 +	 * adds a summary of length changes to buf_out1/buf_out2 when called. */
  1.1223 +	/* size: 0-> 36. */
  1.1224 +	evbuffer_add_printf(buf, "The %d magic words are spotty pudding", 2);
  1.1225 +	evbuffer_validate(buf);
  1.1226 +	evbuffer_cb_clear_flags(buf, cb2, EVBUFFER_CB_ENABLED);
  1.1227 +	evbuffer_drain(buf, 10); /*36->26*/
  1.1228 +	evbuffer_validate(buf);
  1.1229 +	evbuffer_prepend(buf, "Hello", 5);/*26->31*/
  1.1230 +	evbuffer_cb_set_flags(buf, cb2, EVBUFFER_CB_ENABLED);
  1.1231 +	evbuffer_add_reference(buf, "Goodbye", 7, NULL, NULL); /*31->38*/
  1.1232 +	evbuffer_remove_cb_entry(buf, cb1);
  1.1233 +	evbuffer_validate(buf);
  1.1234 +	evbuffer_drain(buf, evbuffer_get_length(buf)); /*38->0*/;
  1.1235 +	tt_assert(-1 == evbuffer_remove_cb(buf, log_change_callback, NULL));
  1.1236 +	evbuffer_add(buf, "X", 1); /* 0->1 */
  1.1237 +	tt_assert(!evbuffer_remove_cb(buf, log_change_callback, buf_out2));
  1.1238 +	evbuffer_validate(buf);
  1.1239 +
  1.1240 +	tt_str_op(evbuffer_pullup(buf_out1, -1), ==,
  1.1241 +		  "0->36; 36->26; 26->31; 31->38; ");
  1.1242 +	tt_str_op(evbuffer_pullup(buf_out2, -1), ==,
  1.1243 +		  "0->36; 31->38; 38->0; 0->1; ");
  1.1244 +	evbuffer_drain(buf_out1, evbuffer_get_length(buf_out1));
  1.1245 +	evbuffer_drain(buf_out2, evbuffer_get_length(buf_out2));
  1.1246 +	/* Let's test the obsolete buffer_setcb function too. */
  1.1247 +	cb1 = evbuffer_add_cb(buf, log_change_callback, buf_out1);
  1.1248 +	tt_assert(cb1 != NULL);
  1.1249 +	cb2 = evbuffer_add_cb(buf, log_change_callback, buf_out2);
  1.1250 +	tt_assert(cb2 != NULL);
  1.1251 +	evbuffer_setcb(buf, self_draining_callback, NULL);
  1.1252 +	evbuffer_add_printf(buf, "This should get drained right away.");
  1.1253 +	tt_uint_op(evbuffer_get_length(buf), ==, 0);
  1.1254 +	tt_uint_op(evbuffer_get_length(buf_out1), ==, 0);
  1.1255 +	tt_uint_op(evbuffer_get_length(buf_out2), ==, 0);
  1.1256 +	evbuffer_setcb(buf, NULL, NULL);
  1.1257 +	evbuffer_add_printf(buf, "This will not.");
  1.1258 +	tt_str_op(evbuffer_pullup(buf, -1), ==, "This will not.");
  1.1259 +	evbuffer_validate(buf);
  1.1260 +	evbuffer_drain(buf, evbuffer_get_length(buf));
  1.1261 +	evbuffer_validate(buf);
  1.1262 +#if 0
  1.1263 +	/* Now let's try a suspended callback. */
  1.1264 +	cb1 = evbuffer_add_cb(buf, log_change_callback, buf_out1);
  1.1265 +	cb2 = evbuffer_add_cb(buf, log_change_callback, buf_out2);
  1.1266 +	evbuffer_cb_suspend(buf,cb2);
  1.1267 +	evbuffer_prepend(buf,"Hello world",11); /*0->11*/
  1.1268 +	evbuffer_validate(buf);
  1.1269 +	evbuffer_cb_suspend(buf,cb1);
  1.1270 +	evbuffer_add(buf,"more",4); /* 11->15 */
  1.1271 +	evbuffer_cb_unsuspend(buf,cb2);
  1.1272 +	evbuffer_drain(buf, 4); /* 15->11 */
  1.1273 +	evbuffer_cb_unsuspend(buf,cb1);
  1.1274 +	evbuffer_drain(buf, evbuffer_get_length(buf)); /* 11->0 */
  1.1275 +
  1.1276 +	tt_str_op(evbuffer_pullup(buf_out1, -1), ==,
  1.1277 +		  "0->11; 11->11; 11->0; ");
  1.1278 +	tt_str_op(evbuffer_pullup(buf_out2, -1), ==,
  1.1279 +		  "0->15; 15->11; 11->0; ");
  1.1280 +#endif
  1.1281 +
  1.1282 + end:
  1.1283 +	if (buf)
  1.1284 +		evbuffer_free(buf);
  1.1285 +	if (buf_out1)
  1.1286 +		evbuffer_free(buf_out1);
  1.1287 +	if (buf_out2)
  1.1288 +		evbuffer_free(buf_out2);
  1.1289 +}
  1.1290 +
  1.1291 +static int ref_done_cb_called_count = 0;
  1.1292 +static void *ref_done_cb_called_with = NULL;
  1.1293 +static const void *ref_done_cb_called_with_data = NULL;
  1.1294 +static size_t ref_done_cb_called_with_len = 0;
  1.1295 +static void ref_done_cb(const void *data, size_t len, void *info)
  1.1296 +{
  1.1297 +	++ref_done_cb_called_count;
  1.1298 +	ref_done_cb_called_with = info;
  1.1299 +	ref_done_cb_called_with_data = data;
  1.1300 +	ref_done_cb_called_with_len = len;
  1.1301 +}
  1.1302 +
  1.1303 +static void
  1.1304 +test_evbuffer_add_reference(void *ptr)
  1.1305 +{
  1.1306 +	const char chunk1[] = "If you have found the answer to such a problem";
  1.1307 +	const char chunk2[] = "you ought to write it up for publication";
  1.1308 +			  /* -- Knuth's "Notes on the Exercises" from TAOCP */
  1.1309 +	char tmp[16];
  1.1310 +	size_t len1 = strlen(chunk1), len2=strlen(chunk2);
  1.1311 +
  1.1312 +	struct evbuffer *buf1 = NULL, *buf2 = NULL;
  1.1313 +
  1.1314 +	buf1 = evbuffer_new();
  1.1315 +	tt_assert(buf1);
  1.1316 +
  1.1317 +	evbuffer_add_reference(buf1, chunk1, len1, ref_done_cb, (void*)111);
  1.1318 +	evbuffer_add(buf1, ", ", 2);
  1.1319 +	evbuffer_add_reference(buf1, chunk2, len2, ref_done_cb, (void*)222);
  1.1320 +	tt_int_op(evbuffer_get_length(buf1), ==, len1+len2+2);
  1.1321 +
  1.1322 +	/* Make sure we can drain a little from a reference. */
  1.1323 +	tt_int_op(evbuffer_remove(buf1, tmp, 6), ==, 6);
  1.1324 +	tt_int_op(memcmp(tmp, "If you", 6), ==, 0);
  1.1325 +	tt_int_op(evbuffer_remove(buf1, tmp, 5), ==, 5);
  1.1326 +	tt_int_op(memcmp(tmp, " have", 5), ==, 0);
  1.1327 +
  1.1328 +	/* Make sure that prepending does not meddle with immutable data */
  1.1329 +	tt_int_op(evbuffer_prepend(buf1, "I have ", 7), ==, 0);
  1.1330 +	tt_int_op(memcmp(chunk1, "If you", 6), ==, 0);
  1.1331 +	evbuffer_validate(buf1);
  1.1332 +
  1.1333 +	/* Make sure that when the chunk is over, the callback is invoked. */
  1.1334 +	evbuffer_drain(buf1, 7); /* Remove prepended stuff. */
  1.1335 +	evbuffer_drain(buf1, len1-11-1); /* remove all but one byte of chunk1 */
  1.1336 +	tt_int_op(ref_done_cb_called_count, ==, 0);
  1.1337 +	evbuffer_remove(buf1, tmp, 1);
  1.1338 +	tt_int_op(tmp[0], ==, 'm');
  1.1339 +	tt_assert(ref_done_cb_called_with == (void*)111);
  1.1340 +	tt_assert(ref_done_cb_called_with_data == chunk1);
  1.1341 +	tt_assert(ref_done_cb_called_with_len == len1);
  1.1342 +	tt_int_op(ref_done_cb_called_count, ==, 1);
  1.1343 +	evbuffer_validate(buf1);
  1.1344 +
  1.1345 +	/* Drain some of the remaining chunk, then add it to another buffer */
  1.1346 +	evbuffer_drain(buf1, 6); /* Remove the ", you ". */
  1.1347 +	buf2 = evbuffer_new();
  1.1348 +	tt_assert(buf2);
  1.1349 +	tt_int_op(ref_done_cb_called_count, ==, 1);
  1.1350 +	evbuffer_add(buf2, "I ", 2);
  1.1351 +
  1.1352 +	evbuffer_add_buffer(buf2, buf1);
  1.1353 +	tt_int_op(ref_done_cb_called_count, ==, 1);
  1.1354 +	evbuffer_remove(buf2, tmp, 16);
  1.1355 +	tt_int_op(memcmp("I ought to write", tmp, 16), ==, 0);
  1.1356 +	evbuffer_drain(buf2, evbuffer_get_length(buf2));
  1.1357 +	tt_int_op(ref_done_cb_called_count, ==, 2);
  1.1358 +	tt_assert(ref_done_cb_called_with == (void*)222);
  1.1359 +	evbuffer_validate(buf2);
  1.1360 +
  1.1361 +	/* Now add more stuff to buf1 and make sure that it gets removed on
  1.1362 +	 * free. */
  1.1363 +	evbuffer_add(buf1, "You shake and shake the ", 24);
  1.1364 +	evbuffer_add_reference(buf1, "ketchup bottle", 14, ref_done_cb,
  1.1365 +	    (void*)3333);
  1.1366 +	evbuffer_add(buf1, ". Nothing comes and then a lot'll.", 42);
  1.1367 +	evbuffer_free(buf1);
  1.1368 +	buf1 = NULL;
  1.1369 +	tt_int_op(ref_done_cb_called_count, ==, 3);
  1.1370 +	tt_assert(ref_done_cb_called_with == (void*)3333);
  1.1371 +
  1.1372 +end:
  1.1373 +	if (buf1)
  1.1374 +		evbuffer_free(buf1);
  1.1375 +	if (buf2)
  1.1376 +		evbuffer_free(buf2);
  1.1377 +}
  1.1378 +
  1.1379 +/* Some cases that we didn't get in test_evbuffer() above, for more coverage. */
  1.1380 +static void
  1.1381 +test_evbuffer_prepend(void *ptr)
  1.1382 +{
  1.1383 +	struct evbuffer *buf1 = NULL, *buf2 = NULL;
  1.1384 +	char tmp[128];
  1.1385 +	int n;
  1.1386 +
  1.1387 +	buf1 = evbuffer_new();
  1.1388 +	tt_assert(buf1);
  1.1389 +
  1.1390 +	/* Case 0: The evbuffer is entirely empty. */
  1.1391 +	evbuffer_prepend(buf1, "This string has 29 characters", 29);
  1.1392 +	evbuffer_validate(buf1);
  1.1393 +
  1.1394 +	/* Case 1: Prepend goes entirely in new chunk. */
  1.1395 +	evbuffer_prepend(buf1, "Short.", 6);
  1.1396 +	evbuffer_validate(buf1);
  1.1397 +
  1.1398 +	/* Case 2: prepend goes entirely in first chunk. */
  1.1399 +	evbuffer_drain(buf1, 6+11);
  1.1400 +	evbuffer_prepend(buf1, "it", 2);
  1.1401 +	evbuffer_validate(buf1);
  1.1402 +	tt_assert(!memcmp(buf1->first->buffer+buf1->first->misalign,
  1.1403 +		"it has", 6));
  1.1404 +
  1.1405 +	/* Case 3: prepend is split over multiple chunks. */
  1.1406 +	evbuffer_prepend(buf1, "It is no longer true to say ", 28);
  1.1407 +	evbuffer_validate(buf1);
  1.1408 +	n = evbuffer_remove(buf1, tmp, sizeof(tmp)-1);
  1.1409 +	tmp[n]='\0';
  1.1410 +	tt_str_op(tmp,==,"It is no longer true to say it has 29 characters");
  1.1411 +
  1.1412 +	buf2 = evbuffer_new();
  1.1413 +	tt_assert(buf2);
  1.1414 +
  1.1415 +	/* Case 4: prepend a buffer to an empty buffer. */
  1.1416 +	n = 999;
  1.1417 +	evbuffer_add_printf(buf1, "Here is string %d. ", n++);
  1.1418 +	evbuffer_prepend_buffer(buf2, buf1);
  1.1419 +	evbuffer_validate(buf2);
  1.1420 +
  1.1421 +	/* Case 5: prepend a buffer to a nonempty buffer. */
  1.1422 +	evbuffer_add_printf(buf1, "Here is string %d. ", n++);
  1.1423 +	evbuffer_prepend_buffer(buf2, buf1);
  1.1424 +	evbuffer_validate(buf2);
  1.1425 +	evbuffer_validate(buf1);
  1.1426 +	n = evbuffer_remove(buf2, tmp, sizeof(tmp)-1);
  1.1427 +	tmp[n]='\0';
  1.1428 +	tt_str_op(tmp,==,"Here is string 1000. Here is string 999. ");
  1.1429 +
  1.1430 +end:
  1.1431 +	if (buf1)
  1.1432 +		evbuffer_free(buf1);
  1.1433 +	if (buf2)
  1.1434 +		evbuffer_free(buf2);
  1.1435 +
  1.1436 +}
  1.1437 +
  1.1438 +static void
  1.1439 +test_evbuffer_peek(void *info)
  1.1440 +{
  1.1441 +	struct evbuffer *buf = NULL, *tmp_buf = NULL;
  1.1442 +	int i;
  1.1443 +	struct evbuffer_iovec v[20];
  1.1444 +	struct evbuffer_ptr ptr;
  1.1445 +
  1.1446 +#define tt_iov_eq(v, s)						\
  1.1447 +	tt_int_op((v)->iov_len, ==, strlen(s));			\
  1.1448 +	tt_assert(!memcmp((v)->iov_base, (s), strlen(s)))
  1.1449 +
  1.1450 +	/* Let's make a very fragmented buffer. */
  1.1451 +	buf = evbuffer_new();
  1.1452 +	tmp_buf = evbuffer_new();
  1.1453 +	for (i = 0; i < 16; ++i) {
  1.1454 +		evbuffer_add_printf(tmp_buf, "Contents of chunk [%d]\n", i);
  1.1455 +		evbuffer_add_buffer(buf, tmp_buf);
  1.1456 +	}
  1.1457 +
  1.1458 +	/* How many chunks do we need for everything? */
  1.1459 +	i = evbuffer_peek(buf, -1, NULL, NULL, 0);
  1.1460 +	tt_int_op(i, ==, 16);
  1.1461 +
  1.1462 +	/* Simple peek: get everything. */
  1.1463 +	i = evbuffer_peek(buf, -1, NULL, v, 20);
  1.1464 +	tt_int_op(i, ==, 16); /* we used only 16 chunks. */
  1.1465 +	tt_iov_eq(&v[0], "Contents of chunk [0]\n");
  1.1466 +	tt_iov_eq(&v[3], "Contents of chunk [3]\n");
  1.1467 +	tt_iov_eq(&v[12], "Contents of chunk [12]\n");
  1.1468 +	tt_iov_eq(&v[15], "Contents of chunk [15]\n");
  1.1469 +
  1.1470 +	/* Just get one chunk worth. */
  1.1471 +	memset(v, 0, sizeof(v));
  1.1472 +	i = evbuffer_peek(buf, -1, NULL, v, 1);
  1.1473 +	tt_int_op(i, ==, 1);
  1.1474 +	tt_iov_eq(&v[0], "Contents of chunk [0]\n");
  1.1475 +	tt_assert(v[1].iov_base == NULL);
  1.1476 +
  1.1477 +	/* Suppose we want at least the first 40 bytes. */
  1.1478 +	memset(v, 0, sizeof(v));
  1.1479 +	i = evbuffer_peek(buf, 40, NULL, v, 16);
  1.1480 +	tt_int_op(i, ==, 2);
  1.1481 +	tt_iov_eq(&v[0], "Contents of chunk [0]\n");
  1.1482 +	tt_iov_eq(&v[1], "Contents of chunk [1]\n");
  1.1483 +	tt_assert(v[2].iov_base == NULL);
  1.1484 +
  1.1485 +	/* How many chunks do we need for 100 bytes? */
  1.1486 +	memset(v, 0, sizeof(v));
  1.1487 +	i = evbuffer_peek(buf, 100, NULL, NULL, 0);
  1.1488 +	tt_int_op(i, ==, 5);
  1.1489 +	tt_assert(v[0].iov_base == NULL);
  1.1490 +
  1.1491 +	/* Now we ask for more bytes than we provide chunks for */
  1.1492 +	memset(v, 0, sizeof(v));
  1.1493 +	i = evbuffer_peek(buf, 60, NULL, v, 1);
  1.1494 +	tt_int_op(i, ==, 3);
  1.1495 +	tt_iov_eq(&v[0], "Contents of chunk [0]\n");
  1.1496 +	tt_assert(v[1].iov_base == NULL);
  1.1497 +
  1.1498 +	/* Now we ask for more bytes than the buffer has. */
  1.1499 +	memset(v, 0, sizeof(v));
  1.1500 +	i = evbuffer_peek(buf, 65536, NULL, v, 20);
  1.1501 +	tt_int_op(i, ==, 16); /* we used only 16 chunks. */
  1.1502 +	tt_iov_eq(&v[0], "Contents of chunk [0]\n");
  1.1503 +	tt_iov_eq(&v[3], "Contents of chunk [3]\n");
  1.1504 +	tt_iov_eq(&v[12], "Contents of chunk [12]\n");
  1.1505 +	tt_iov_eq(&v[15], "Contents of chunk [15]\n");
  1.1506 +	tt_assert(v[16].iov_base == NULL);
  1.1507 +
  1.1508 +	/* What happens if we try an empty buffer? */
  1.1509 +	memset(v, 0, sizeof(v));
  1.1510 +	i = evbuffer_peek(tmp_buf, -1, NULL, v, 20);
  1.1511 +	tt_int_op(i, ==, 0);
  1.1512 +	tt_assert(v[0].iov_base == NULL);
  1.1513 +	memset(v, 0, sizeof(v));
  1.1514 +	i = evbuffer_peek(tmp_buf, 50, NULL, v, 20);
  1.1515 +	tt_int_op(i, ==, 0);
  1.1516 +	tt_assert(v[0].iov_base == NULL);
  1.1517 +
  1.1518 +	/* Okay, now time to have fun with pointers. */
  1.1519 +	memset(v, 0, sizeof(v));
  1.1520 +	evbuffer_ptr_set(buf, &ptr, 30, EVBUFFER_PTR_SET);
  1.1521 +	i = evbuffer_peek(buf, 50, &ptr, v, 20);
  1.1522 +	tt_int_op(i, ==, 3);
  1.1523 +	tt_iov_eq(&v[0], " of chunk [1]\n");
  1.1524 +	tt_iov_eq(&v[1], "Contents of chunk [2]\n");
  1.1525 +	tt_iov_eq(&v[2], "Contents of chunk [3]\n"); /*more than we asked for*/
  1.1526 +
  1.1527 +	/* advance to the start of another chain. */
  1.1528 +	memset(v, 0, sizeof(v));
  1.1529 +	evbuffer_ptr_set(buf, &ptr, 14, EVBUFFER_PTR_ADD);
  1.1530 +	i = evbuffer_peek(buf, 44, &ptr, v, 20);
  1.1531 +	tt_int_op(i, ==, 2);
  1.1532 +	tt_iov_eq(&v[0], "Contents of chunk [2]\n");
  1.1533 +	tt_iov_eq(&v[1], "Contents of chunk [3]\n"); /*more than we asked for*/
  1.1534 +
  1.1535 +end:
  1.1536 +	if (buf)
  1.1537 +		evbuffer_free(buf);
  1.1538 +	if (tmp_buf)
  1.1539 +		evbuffer_free(tmp_buf);
  1.1540 +}
  1.1541 +
  1.1542 +/* Check whether evbuffer freezing works right.  This is called twice,
  1.1543 +   once with the argument "start" and once with the argument "end".
  1.1544 +   When we test "start", we freeze the start of an evbuffer and make sure
  1.1545 +   that modifying the start of the buffer doesn't work.  When we test
  1.1546 +   "end", we freeze the end of an evbuffer and make sure that modifying
  1.1547 +   the end of the buffer doesn't work.
  1.1548 + */
  1.1549 +static void
  1.1550 +test_evbuffer_freeze(void *ptr)
  1.1551 +{
  1.1552 +	struct evbuffer *buf = NULL, *tmp_buf=NULL;
  1.1553 +	const char string[] = /* Year's End, Richard Wilbur */
  1.1554 +	    "I've known the wind by water banks to shake\n"
  1.1555 +	    "The late leaves down, which frozen where they fell\n"
  1.1556 +	    "And held in ice as dancers in a spell\n"
  1.1557 +	    "Fluttered all winter long into a lake...";
  1.1558 +	const int start = !strcmp(ptr, "start");
  1.1559 +	char *cp;
  1.1560 +	char charbuf[128];
  1.1561 +	int r;
  1.1562 +	size_t orig_length;
  1.1563 +	struct evbuffer_iovec v[1];
  1.1564 +
  1.1565 +	if (!start)
  1.1566 +		tt_str_op(ptr, ==, "end");
  1.1567 +
  1.1568 +	buf = evbuffer_new();
  1.1569 +	tmp_buf = evbuffer_new();
  1.1570 +	tt_assert(tmp_buf);
  1.1571 +
  1.1572 +	evbuffer_add(buf, string, strlen(string));
  1.1573 +	evbuffer_freeze(buf, start); /* Freeze the start or the end.*/
  1.1574 +
  1.1575 +#define FREEZE_EQ(a, startcase, endcase)		\
  1.1576 +	do {						\
  1.1577 +	    if (start) {				\
  1.1578 +		    tt_int_op((a), ==, (startcase));	\
  1.1579 +	    } else {					\
  1.1580 +		    tt_int_op((a), ==, (endcase));	\
  1.1581 +	    }						\
  1.1582 +	} while (0)
  1.1583 +
  1.1584 +
  1.1585 +	orig_length = evbuffer_get_length(buf);
  1.1586 +
  1.1587 +	/* These functions all manipulate the end of buf. */
  1.1588 +	r = evbuffer_add(buf, "abc", 0);
  1.1589 +	FREEZE_EQ(r, 0, -1);
  1.1590 +	r = evbuffer_reserve_space(buf, 10, v, 1);
  1.1591 +	FREEZE_EQ(r, 1, -1);
  1.1592 +	if (r == 0) {
  1.1593 +		memset(v[0].iov_base, 'X', 10);
  1.1594 +		v[0].iov_len = 10;
  1.1595 +	}
  1.1596 +	r = evbuffer_commit_space(buf, v, 1);
  1.1597 +	FREEZE_EQ(r, 0, -1);
  1.1598 +	r = evbuffer_add_reference(buf, string, 5, NULL, NULL);
  1.1599 +	FREEZE_EQ(r, 0, -1);
  1.1600 +	r = evbuffer_add_printf(buf, "Hello %s", "world");
  1.1601 +	FREEZE_EQ(r, 11, -1);
  1.1602 +	/* TODO: test add_buffer, add_file, read */
  1.1603 +
  1.1604 +	if (!start)
  1.1605 +		tt_int_op(orig_length, ==, evbuffer_get_length(buf));
  1.1606 +
  1.1607 +	orig_length = evbuffer_get_length(buf);
  1.1608 +
  1.1609 +	/* These functions all manipulate the start of buf. */
  1.1610 +	r = evbuffer_remove(buf, charbuf, 1);
  1.1611 +	FREEZE_EQ(r, -1, 1);
  1.1612 +	r = evbuffer_drain(buf, 3);
  1.1613 +	FREEZE_EQ(r, -1, 0);
  1.1614 +	r = evbuffer_prepend(buf, "dummy", 5);
  1.1615 +	FREEZE_EQ(r, -1, 0);
  1.1616 +	cp = evbuffer_readln(buf, NULL, EVBUFFER_EOL_LF);
  1.1617 +	FREEZE_EQ(cp==NULL, 1, 0);
  1.1618 +	if (cp)
  1.1619 +		free(cp);
  1.1620 +	/* TODO: Test remove_buffer, add_buffer, write, prepend_buffer */
  1.1621 +
  1.1622 +	if (start)
  1.1623 +		tt_int_op(orig_length, ==, evbuffer_get_length(buf));
  1.1624 +
  1.1625 +end:
  1.1626 +	if (buf)
  1.1627 +		evbuffer_free(buf);
  1.1628 +
  1.1629 +	if (tmp_buf)
  1.1630 +		evbuffer_free(tmp_buf);
  1.1631 +}
  1.1632 +
  1.1633 +static void *
  1.1634 +setup_passthrough(const struct testcase_t *testcase)
  1.1635 +{
  1.1636 +	return testcase->setup_data;
  1.1637 +}
  1.1638 +static int
  1.1639 +cleanup_passthrough(const struct testcase_t *testcase, void *ptr)
  1.1640 +{
  1.1641 +	(void) ptr;
  1.1642 +	return 1;
  1.1643 +}
  1.1644 +
  1.1645 +static const struct testcase_setup_t nil_setup = {
  1.1646 +	setup_passthrough,
  1.1647 +	cleanup_passthrough
  1.1648 +};
  1.1649 +
  1.1650 +struct testcase_t evbuffer_testcases[] = {
  1.1651 +	{ "evbuffer", test_evbuffer, 0, NULL, NULL },
  1.1652 +	{ "remove_buffer_with_empty", test_evbuffer_remove_buffer_with_empty, 0, NULL, NULL },
  1.1653 +	{ "reserve2", test_evbuffer_reserve2, 0, NULL, NULL },
  1.1654 +	{ "reserve_many", test_evbuffer_reserve_many, 0, NULL, NULL },
  1.1655 +	{ "reserve_many2", test_evbuffer_reserve_many, 0, &nil_setup, (void*)"add" },
  1.1656 +	{ "reserve_many3", test_evbuffer_reserve_many, 0, &nil_setup, (void*)"fill" },
  1.1657 +	{ "expand", test_evbuffer_expand, 0, NULL, NULL },
  1.1658 +	{ "reference", test_evbuffer_reference, 0, NULL, NULL },
  1.1659 +	{ "iterative", test_evbuffer_iterative, 0, NULL, NULL },
  1.1660 +	{ "readln", test_evbuffer_readln, TT_NO_LOGS, &basic_setup, NULL },
  1.1661 +	{ "search_eol", test_evbuffer_search_eol, 0, NULL, NULL },
  1.1662 +	{ "find", test_evbuffer_find, 0, NULL, NULL },
  1.1663 +	{ "ptr_set", test_evbuffer_ptr_set, 0, NULL, NULL },
  1.1664 +	{ "search", test_evbuffer_search, 0, NULL, NULL },
  1.1665 +	{ "callbacks", test_evbuffer_callbacks, 0, NULL, NULL },
  1.1666 +	{ "add_reference", test_evbuffer_add_reference, 0, NULL, NULL },
  1.1667 +	{ "prepend", test_evbuffer_prepend, TT_FORK, NULL, NULL },
  1.1668 +	{ "peek", test_evbuffer_peek, 0, NULL, NULL },
  1.1669 +	{ "freeze_start", test_evbuffer_freeze, 0, &nil_setup, (void*)"start" },
  1.1670 +	{ "freeze_end", test_evbuffer_freeze, 0, &nil_setup, (void*)"end" },
  1.1671 +	/* TODO: need a temp file implementation for Windows */
  1.1672 +	{ "add_file_sendfile", test_evbuffer_add_file, TT_FORK, &nil_setup,
  1.1673 +	  (void*)"sendfile" },
  1.1674 +	{ "add_file_mmap", test_evbuffer_add_file, TT_FORK, &nil_setup,
  1.1675 +	  (void*)"mmap" },
  1.1676 +	{ "add_file_linear", test_evbuffer_add_file, TT_FORK, &nil_setup,
  1.1677 +	  (void*)"linear" },
  1.1678 +
  1.1679 +	END_OF_TESTCASES
  1.1680 +};

mercurial