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