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