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