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