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