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