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