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

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

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

mercurial