etc/services - sync with NetBSD-8
[minix.git] / external / bsd / libevent / dist / test / regress_buffer.c
blob61b2d4b3616db97c2273edb58b763f42105b15dc
1 /* $NetBSD: regress_buffer.c,v 1.5 2015/08/28 13:04:48 joerg Exp $ */
2 /*
3 * Copyright (c) 2003-2007 Niels Provos <provos@citi.umich.edu>
4 * Copyright (c) 2007-2012 Niels Provos and Nick Mathewson
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * 3. The name of the author may not be used to endorse or promote products
15 * derived from this software without specific prior written permission.
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 #ifdef WIN32
30 #include <winsock2.h>
31 #include <windows.h>
32 #endif
34 #include "event2/event-config.h"
35 #include <sys/cdefs.h>
36 __RCSID("$NetBSD: regress_buffer.c,v 1.5 2015/08/28 13:04:48 joerg Exp $");
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>
57 #include "event2/event.h"
58 #include "event2/buffer.h"
59 #include "event2/buffer_compat.h"
60 #include "event2/util.h"
62 #include "evbuffer-internal.h"
63 #include "log-internal.h"
65 #include "regress.h"
67 /* Validates that an evbuffer is good. Returns false if it isn't, true if it
68 * is*/
69 static int
70 _evbuffer_validate(struct evbuffer *buf)
72 struct evbuffer_chain *chain;
73 size_t sum = 0;
74 int found_last_with_datap = 0;
76 if (buf->first == NULL) {
77 tt_assert(buf->last == NULL);
78 tt_assert(buf->total_len == 0);
81 chain = buf->first;
83 tt_assert(buf->last_with_datap);
84 if (buf->last_with_datap == &buf->first)
85 found_last_with_datap = 1;
87 while (chain != NULL) {
88 if (&chain->next == buf->last_with_datap)
89 found_last_with_datap = 1;
90 sum += chain->off;
91 if (chain->next == NULL) {
92 tt_assert(buf->last == chain);
94 tt_assert(chain->buffer_len >= chain->misalign + chain->off);
95 chain = chain->next;
98 if (buf->first)
99 tt_assert(*buf->last_with_datap);
101 if (*buf->last_with_datap) {
102 chain = *buf->last_with_datap;
103 if (chain->off == 0 || buf->total_len == 0) {
104 tt_assert(chain->off == 0)
105 tt_assert(chain == buf->first);
106 tt_assert(buf->total_len == 0);
108 chain = chain->next;
109 while (chain != NULL) {
110 tt_assert(chain->off == 0);
111 chain = chain->next;
113 } else {
114 tt_assert(buf->last_with_datap == &buf->first);
116 tt_assert(found_last_with_datap);
118 tt_assert(sum == buf->total_len);
119 return 1;
120 end:
121 return 0;
124 static void
125 evbuffer_get_waste(struct evbuffer *buf, size_t *allocatedp, size_t *wastedp, size_t *usedp)
127 struct evbuffer_chain *chain;
128 size_t a, w, u;
129 int n = 0;
130 u = a = w = 0;
132 chain = buf->first;
133 /* skip empty at start */
134 while (chain && chain->off==0) {
135 ++n;
136 a += chain->buffer_len;
137 chain = chain->next;
139 /* first nonempty chain: stuff at the end only is wasted. */
140 if (chain) {
141 ++n;
142 a += chain->buffer_len;
143 u += chain->off;
144 if (chain->next && chain->next->off)
145 w += (size_t)(chain->buffer_len - (chain->misalign + chain->off));
146 chain = chain->next;
148 /* subsequent nonempty chains */
149 while (chain && chain->off) {
150 ++n;
151 a += chain->buffer_len;
152 w += (size_t)chain->misalign;
153 u += chain->off;
154 if (chain->next && chain->next->off)
155 w += (size_t) (chain->buffer_len - (chain->misalign + chain->off));
156 chain = chain->next;
158 /* subsequent empty chains */
159 while (chain) {
160 ++n;
161 a += chain->buffer_len;
163 *allocatedp = a;
164 *wastedp = w;
165 *usedp = u;
168 #define evbuffer_validate(buf) \
169 TT_STMT_BEGIN if (!_evbuffer_validate(buf)) TT_DIE(("Buffer format invalid")); TT_STMT_END
171 static void
172 test_evbuffer(void *ptr)
174 static char buffer[512], *tmp;
175 struct evbuffer *evb = evbuffer_new();
176 struct evbuffer *evb_two = evbuffer_new();
177 size_t sz_tmp;
178 int i;
180 evbuffer_validate(evb);
181 evbuffer_add_printf(evb, "%s/%d", "hello", 1);
182 evbuffer_validate(evb);
184 tt_assert(evbuffer_get_length(evb) == 7);
185 tt_assert(!memcmp((char*)EVBUFFER_DATA(evb), "hello/1", 1));
187 evbuffer_add_buffer(evb, evb_two);
188 evbuffer_validate(evb);
190 evbuffer_drain(evb, strlen("hello/"));
191 evbuffer_validate(evb);
192 tt_assert(evbuffer_get_length(evb) == 1);
193 tt_assert(!memcmp((char*)EVBUFFER_DATA(evb), "1", 1));
195 evbuffer_add_printf(evb_two, "%s", "/hello");
196 evbuffer_validate(evb);
197 evbuffer_add_buffer(evb, evb_two);
198 evbuffer_validate(evb);
200 tt_assert(evbuffer_get_length(evb_two) == 0);
201 tt_assert(evbuffer_get_length(evb) == 7);
202 tt_assert(memcmp((char*)EVBUFFER_DATA(evb), "1/hello", 7) == 0);
204 memset(buffer, 0, sizeof(buffer));
205 evbuffer_add(evb, buffer, sizeof(buffer));
206 evbuffer_validate(evb);
207 tt_assert(evbuffer_get_length(evb) == 7 + 512);
209 tmp = (char *)evbuffer_pullup(evb, 7 + 512);
210 tt_assert(tmp);
211 tt_assert(!strncmp(tmp, "1/hello", 7));
212 tt_assert(!memcmp(tmp + 7, buffer, sizeof(buffer)));
213 evbuffer_validate(evb);
215 evbuffer_prepend(evb, "something", 9);
216 evbuffer_validate(evb);
217 evbuffer_prepend(evb, "else", 4);
218 evbuffer_validate(evb);
220 tmp = (char *)evbuffer_pullup(evb, 4 + 9 + 7);
221 tt_assert(!strncmp(tmp, "elsesomething1/hello", 4 + 9 + 7));
222 evbuffer_validate(evb);
224 evbuffer_drain(evb, -1);
225 evbuffer_validate(evb);
226 evbuffer_drain(evb_two, -1);
227 evbuffer_validate(evb);
229 for (i = 0; i < 3; ++i) {
230 evbuffer_add(evb_two, buffer, sizeof(buffer));
231 evbuffer_validate(evb_two);
232 evbuffer_add_buffer(evb, evb_two);
233 evbuffer_validate(evb);
234 evbuffer_validate(evb_two);
237 tt_assert(evbuffer_get_length(evb_two) == 0);
238 tt_assert(evbuffer_get_length(evb) == i * sizeof(buffer));
240 /* test remove buffer */
241 sz_tmp = (size_t)(sizeof(buffer)*2.5);
242 evbuffer_remove_buffer(evb, evb_two, sz_tmp);
243 tt_assert(evbuffer_get_length(evb_two) == sz_tmp);
244 tt_assert(evbuffer_get_length(evb) == sizeof(buffer) / 2);
245 evbuffer_validate(evb);
247 if (memcmp(evbuffer_pullup(
248 evb, -1), buffer, sizeof(buffer) / 2) != 0 ||
249 memcmp(evbuffer_pullup(
250 evb_two, -1), buffer, sizeof(buffer)) != 0)
251 tt_abort_msg("Pullup did not preserve content");
253 evbuffer_validate(evb);
256 /* testing one-vector reserve and commit */
258 struct evbuffer_iovec v[1];
259 char *buf;
260 int ii, j, r;
262 for (ii = 0; ii < 3; ++ii) {
263 r = evbuffer_reserve_space(evb, 10000, v, 1);
264 tt_int_op(r, ==, 1);
265 tt_assert(v[0].iov_len >= 10000);
266 tt_assert(v[0].iov_base != NULL);
268 evbuffer_validate(evb);
269 buf = v[0].iov_base;
270 for (j = 0; j < 10000; ++j) {
271 buf[j] = j;
273 evbuffer_validate(evb);
275 tt_int_op(evbuffer_commit_space(evb, v, 1), ==, 0);
276 evbuffer_validate(evb);
278 tt_assert(evbuffer_get_length(evb) >= 10000);
280 evbuffer_drain(evb, j * 5000);
281 evbuffer_validate(evb);
285 end:
286 evbuffer_free(evb);
287 evbuffer_free(evb_two);
290 static void
291 no_cleanup(const void *data, size_t datalen, void *extra)
295 static void
296 test_evbuffer_remove_buffer_with_empty(void *ptr)
298 struct evbuffer *src = evbuffer_new();
299 struct evbuffer *dst = evbuffer_new();
300 char buf[2];
302 evbuffer_validate(src);
303 evbuffer_validate(dst);
305 /* setup the buffers */
306 /* we need more data in src than we will move later */
307 evbuffer_add_reference(src, buf, sizeof(buf), no_cleanup, NULL);
308 evbuffer_add_reference(src, buf, sizeof(buf), no_cleanup, NULL);
309 /* we need one buffer in dst and one empty buffer at the end */
310 evbuffer_add(dst, buf, sizeof(buf));
311 evbuffer_add_reference(dst, buf, 0, no_cleanup, NULL);
313 evbuffer_validate(src);
314 evbuffer_validate(dst);
316 /* move three bytes over */
317 evbuffer_remove_buffer(src, dst, 3);
319 evbuffer_validate(src);
320 evbuffer_validate(dst);
322 end:
323 evbuffer_free(src);
324 evbuffer_free(dst);
327 static void
328 test_evbuffer_reserve2(void *ptr)
330 /* Test the two-vector cases of reserve/commit. */
331 struct evbuffer *buf = evbuffer_new();
332 int n, i;
333 struct evbuffer_iovec v[2];
334 size_t remaining;
335 char *cp, *cp2;
337 /* First chunk will necessarily be one chunk. Use 512 bytes of it.*/
338 n = evbuffer_reserve_space(buf, 1024, v, 2);
339 tt_int_op(n, ==, 1);
340 tt_int_op(evbuffer_get_length(buf), ==, 0);
341 tt_assert(v[0].iov_base != NULL);
342 tt_int_op(v[0].iov_len, >=, 1024);
343 memset(v[0].iov_base, 'X', 512);
344 cp = v[0].iov_base;
345 remaining = v[0].iov_len - 512;
346 v[0].iov_len = 512;
347 evbuffer_validate(buf);
348 tt_int_op(0, ==, evbuffer_commit_space(buf, v, 1));
349 tt_int_op(evbuffer_get_length(buf), ==, 512);
350 evbuffer_validate(buf);
352 /* Ask for another same-chunk request, in an existing chunk. Use 8
353 * bytes of it. */
354 n = evbuffer_reserve_space(buf, 32, v, 2);
355 tt_int_op(n, ==, 1);
356 tt_assert(cp + 512 == v[0].iov_base);
357 tt_int_op(remaining, ==, v[0].iov_len);
358 memset(v[0].iov_base, 'Y', 8);
359 v[0].iov_len = 8;
360 tt_int_op(0, ==, evbuffer_commit_space(buf, v, 1));
361 tt_int_op(evbuffer_get_length(buf), ==, 520);
362 remaining -= 8;
363 evbuffer_validate(buf);
365 /* Now ask for a request that will be split. Use only one byte of it,
366 though. */
367 n = evbuffer_reserve_space(buf, remaining+64, v, 2);
368 tt_int_op(n, ==, 2);
369 tt_assert(cp + 520 == v[0].iov_base);
370 tt_int_op(remaining, ==, v[0].iov_len);
371 tt_assert(v[1].iov_base);
372 tt_assert(v[1].iov_len >= 64);
373 cp2 = v[1].iov_base;
374 memset(v[0].iov_base, 'Z', 1);
375 v[0].iov_len = 1;
376 tt_int_op(0, ==, evbuffer_commit_space(buf, v, 1));
377 tt_int_op(evbuffer_get_length(buf), ==, 521);
378 remaining -= 1;
379 evbuffer_validate(buf);
381 /* Now ask for a request that will be split. Use some of the first
382 * part and some of the second. */
383 n = evbuffer_reserve_space(buf, remaining+64, v, 2);
384 evbuffer_validate(buf);
385 tt_int_op(n, ==, 2);
386 tt_assert(cp + 521 == v[0].iov_base);
387 tt_int_op(remaining, ==, v[0].iov_len);
388 tt_assert(v[1].iov_base == cp2);
389 tt_assert(v[1].iov_len >= 64);
390 memset(v[0].iov_base, 'W', 400);
391 v[0].iov_len = 400;
392 memset(v[1].iov_base, 'x', 60);
393 v[1].iov_len = 60;
394 tt_int_op(0, ==, evbuffer_commit_space(buf, v, 2));
395 tt_int_op(evbuffer_get_length(buf), ==, 981);
396 evbuffer_validate(buf);
398 /* Now peek to make sure stuff got made how we like. */
399 memset(v,0,sizeof(v));
400 n = evbuffer_peek(buf, -1, NULL, v, 2);
401 tt_int_op(n, ==, 2);
402 tt_int_op(v[0].iov_len, ==, 921);
403 tt_int_op(v[1].iov_len, ==, 60);
405 cp = v[0].iov_base;
406 for (i=0; i<512; ++i)
407 tt_int_op(cp[i], ==, 'X');
408 for (i=512; i<520; ++i)
409 tt_int_op(cp[i], ==, 'Y');
410 for (i=520; i<521; ++i)
411 tt_int_op(cp[i], ==, 'Z');
412 for (i=521; i<921; ++i)
413 tt_int_op(cp[i], ==, 'W');
415 cp = v[1].iov_base;
416 for (i=0; i<60; ++i)
417 tt_int_op(cp[i], ==, 'x');
419 end:
420 evbuffer_free(buf);
423 static void
424 test_evbuffer_reserve_many(void *ptr)
426 /* This is a glass-box test to handle expanding a buffer with more
427 * chunks and reallocating chunks as needed */
428 struct evbuffer *buf = evbuffer_new();
429 struct evbuffer_iovec v[8];
430 int n;
431 size_t sz;
432 int add_data = ptr && !strcmp(ptr, "add");
433 int fill_first = ptr && !strcmp(ptr, "fill");
434 char *cp1, *cp2;
436 /* When reserving the the first chunk, we just allocate it */
437 n = evbuffer_reserve_space(buf, 128, v, 2);
438 evbuffer_validate(buf);
439 tt_int_op(n, ==, 1);
440 tt_assert(v[0].iov_len >= 128);
441 sz = v[0].iov_len;
442 cp1 = v[0].iov_base;
443 if (add_data) {
444 *(char*)v[0].iov_base = 'X';
445 v[0].iov_len = 1;
446 n = evbuffer_commit_space(buf, v, 1);
447 tt_int_op(n, ==, 0);
448 } else if (fill_first) {
449 memset(v[0].iov_base, 'X', v[0].iov_len);
450 n = evbuffer_commit_space(buf, v, 1);
451 tt_int_op(n, ==, 0);
452 n = evbuffer_reserve_space(buf, 128, v, 2);
453 tt_int_op(n, ==, 1);
454 sz = v[0].iov_len;
455 tt_assert(v[0].iov_base != cp1);
456 cp1 = v[0].iov_base;
459 /* Make another chunk get added. */
460 n = evbuffer_reserve_space(buf, sz+128, v, 2);
461 evbuffer_validate(buf);
462 tt_int_op(n, ==, 2);
463 sz = v[0].iov_len + v[1].iov_len;
464 tt_int_op(sz, >=, v[0].iov_len+128);
465 if (add_data) {
466 tt_assert(v[0].iov_base == cp1 + 1);
467 } else {
468 tt_assert(v[0].iov_base == cp1);
470 cp1 = v[0].iov_base;
471 cp2 = v[1].iov_base;
473 /* And a third chunk. */
474 n = evbuffer_reserve_space(buf, sz+128, v, 3);
475 evbuffer_validate(buf);
476 tt_int_op(n, ==, 3);
477 tt_assert(cp1 == v[0].iov_base);
478 tt_assert(cp2 == v[1].iov_base);
479 sz = v[0].iov_len + v[1].iov_len + v[2].iov_len;
481 /* Now force a reallocation by asking for more space in only 2
482 * buffers. */
483 n = evbuffer_reserve_space(buf, sz+128, v, 2);
484 evbuffer_validate(buf);
485 if (add_data) {
486 tt_int_op(n, ==, 2);
487 tt_assert(cp1 == v[0].iov_base);
488 } else {
489 tt_int_op(n, ==, 1);
492 end:
493 evbuffer_free(buf);
496 static void
497 test_evbuffer_expand(void *ptr)
499 char data[4096];
500 struct evbuffer *buf;
501 size_t a,w,u;
502 void *buffer;
504 memset(data, 'X', sizeof(data));
506 /* Make sure that expand() works on an empty buffer */
507 buf = evbuffer_new();
508 tt_int_op(evbuffer_expand(buf, 20000), ==, 0);
509 evbuffer_validate(buf);
510 a=w=u=0;
511 evbuffer_get_waste(buf, &a,&w,&u);
512 tt_assert(w == 0);
513 tt_assert(u == 0);
514 tt_assert(a >= 20000);
515 tt_assert(buf->first);
516 tt_assert(buf->first == buf->last);
517 tt_assert(buf->first->off == 0);
518 tt_assert(buf->first->buffer_len >= 20000);
520 /* Make sure that expand() works as a no-op when there's enough
521 * contiguous space already. */
522 buffer = buf->first->buffer;
523 evbuffer_add(buf, data, 1024);
524 tt_int_op(evbuffer_expand(buf, 1024), ==, 0);
525 tt_assert(buf->first->buffer == buffer);
526 evbuffer_validate(buf);
527 evbuffer_free(buf);
529 /* Make sure that expand() can work by moving misaligned data
530 * when it makes sense to do so. */
531 buf = evbuffer_new();
532 evbuffer_add(buf, data, 400);
534 int n = (int)(buf->first->buffer_len - buf->first->off - 1);
535 tt_assert(n < (int)sizeof(data));
536 evbuffer_add(buf, data, n);
538 tt_assert(buf->first == buf->last);
539 tt_assert(buf->first->off == buf->first->buffer_len - 1);
540 evbuffer_drain(buf, buf->first->off - 1);
541 tt_assert(1 == evbuffer_get_length(buf));
542 tt_assert(buf->first->misalign > 0);
543 tt_assert(buf->first->off == 1);
544 buffer = buf->first->buffer;
545 tt_assert(evbuffer_expand(buf, 40) == 0);
546 tt_assert(buf->first == buf->last);
547 tt_assert(buf->first->off == 1);
548 tt_assert(buf->first->buffer == buffer);
549 tt_assert(buf->first->misalign == 0);
550 evbuffer_validate(buf);
551 evbuffer_free(buf);
553 /* add, expand, pull-up: This used to crash libevent. */
554 buf = evbuffer_new();
556 evbuffer_add(buf, data, sizeof(data));
557 evbuffer_add(buf, data, sizeof(data));
558 evbuffer_add(buf, data, sizeof(data));
560 evbuffer_validate(buf);
561 evbuffer_expand(buf, 1024);
562 evbuffer_validate(buf);
563 evbuffer_pullup(buf, -1);
564 evbuffer_validate(buf);
566 end:
567 evbuffer_free(buf);
571 static int reference_cb_called;
572 static void
573 reference_cb(const void *data, size_t len, void *extra)
575 tt_str_op(data, ==, "this is what we add as read-only memory.");
576 tt_int_op(len, ==, strlen(data));
577 tt_want(extra == (void *)0xdeadaffe);
578 ++reference_cb_called;
579 end:
583 static void
584 test_evbuffer_reference(void *ptr)
586 struct evbuffer *src = evbuffer_new();
587 struct evbuffer *dst = evbuffer_new();
588 struct evbuffer_iovec v[1];
589 const char *data = "this is what we add as read-only memory.";
590 reference_cb_called = 0;
592 tt_assert(evbuffer_add_reference(src, data, strlen(data),
593 reference_cb, (void *)0xdeadaffe) != -1);
595 evbuffer_reserve_space(dst, strlen(data), v, 1);
596 tt_assert(evbuffer_remove(src, v[0].iov_base, 10) != -1);
598 evbuffer_validate(src);
599 evbuffer_validate(dst);
601 /* make sure that we don't write data at the beginning */
602 evbuffer_prepend(src, "aaaaa", 5);
603 evbuffer_validate(src);
604 evbuffer_drain(src, 5);
606 tt_assert(evbuffer_remove(src, ((char*)(v[0].iov_base)) + 10,
607 strlen(data) - 10) != -1);
609 v[0].iov_len = strlen(data);
611 evbuffer_commit_space(dst, v, 1);
612 evbuffer_validate(src);
613 evbuffer_validate(dst);
615 tt_int_op(reference_cb_called, ==, 1);
617 tt_assert(!memcmp(evbuffer_pullup(dst, strlen(data)),
618 data, strlen(data)));
619 evbuffer_validate(dst);
621 end:
622 evbuffer_free(dst);
623 evbuffer_free(src);
626 int _evbuffer_testing_use_sendfile(void);
627 int _evbuffer_testing_use_mmap(void);
628 int _evbuffer_testing_use_linear_file_access(void);
630 static void
631 test_evbuffer_add_file(void *ptr)
633 const char *impl = ptr;
634 struct evbuffer *src = evbuffer_new();
635 const char *data = "this is what we add as file system data.";
636 size_t datalen;
637 const char *compare;
638 int fd = -1;
639 evutil_socket_t xpair[2] = {-1, -1};
640 int r=0, n_written=0;
642 /* Add a test for a big file. XXXX */
644 tt_assert(impl);
645 if (!strcmp(impl, "sendfile")) {
646 if (!_evbuffer_testing_use_sendfile())
647 tt_skip();
648 TT_BLATHER(("Using sendfile-based implementaion"));
649 } else if (!strcmp(impl, "mmap")) {
650 if (!_evbuffer_testing_use_mmap())
651 tt_skip();
652 TT_BLATHER(("Using mmap-based implementaion"));
653 } else if (!strcmp(impl, "linear")) {
654 if (!_evbuffer_testing_use_linear_file_access())
655 tt_skip();
656 TT_BLATHER(("Using read-based implementaion"));
657 } else {
658 TT_DIE(("Didn't recognize the implementation"));
661 /* Say that it drains to a fd so that we can use sendfile. */
662 evbuffer_set_flags(src, EVBUFFER_FLAG_DRAINS_TO_FD);
664 #if defined(_EVENT_HAVE_SENDFILE) && defined(__sun__) && defined(__svr4__)
665 /* We need to use a pair of AF_INET sockets, since Solaris
666 doesn't support sendfile() over AF_UNIX. */
667 if (evutil_ersatz_socketpair(AF_INET, SOCK_STREAM, 0, xpair) == -1)
668 tt_abort_msg("ersatz_socketpair failed");
669 #else
670 if (evutil_socketpair(AF_UNIX, SOCK_STREAM, 0, xpair) == -1)
671 tt_abort_msg("socketpair failed");
672 #endif
674 datalen = strlen(data);
675 fd = regress_make_tmpfile(data, datalen);
677 tt_assert(fd != -1);
679 tt_assert(evbuffer_add_file(src, fd, 0, datalen) != -1);
681 evbuffer_validate(src);
683 while (evbuffer_get_length(src) &&
684 (r = evbuffer_write(src, xpair[0])) > 0) {
685 evbuffer_validate(src);
686 n_written += r;
688 tt_int_op(r, !=, -1);
689 tt_int_op(n_written, ==, datalen);
691 evbuffer_validate(src);
692 tt_int_op(evbuffer_read(src, xpair[1], (int)strlen(data)), ==, datalen);
693 evbuffer_validate(src);
694 compare = (char *)evbuffer_pullup(src, datalen);
695 tt_assert(compare != NULL);
696 if (memcmp(compare, data, datalen))
697 tt_abort_msg("Data from add_file differs.");
699 evbuffer_validate(src);
700 end:
701 if (xpair[0] >= 0)
702 evutil_closesocket(xpair[0]);
703 if (xpair[1] >= 0)
704 evutil_closesocket(xpair[1]);
705 evbuffer_free(src);
708 #ifndef _EVENT_DISABLE_MM_REPLACEMENT
709 static void *
710 failing_malloc(size_t how_much)
712 errno = ENOMEM;
713 return NULL;
715 #endif
717 static void
718 test_evbuffer_readln(void *ptr)
720 struct evbuffer *evb = evbuffer_new();
721 struct evbuffer *evb_tmp = evbuffer_new();
722 const char *s;
723 char *cp = NULL;
724 size_t sz;
726 #define tt_line_eq(content) \
727 TT_STMT_BEGIN \
728 if (!cp || sz != strlen(content) || strcmp(cp, content)) { \
729 TT_DIE(("Wanted %s; got %s [%d]", content, cp, (int)sz)); \
731 TT_STMT_END
733 /* Test EOL_ANY. */
734 s = "complex silly newline\r\n\n\r\n\n\rmore\0\n";
735 evbuffer_add(evb, s, strlen(s)+2);
736 evbuffer_validate(evb);
737 cp = evbuffer_readln(evb, &sz, EVBUFFER_EOL_ANY);
738 tt_line_eq("complex silly newline");
739 free(cp);
740 evbuffer_validate(evb);
741 cp = evbuffer_readln(evb, &sz, EVBUFFER_EOL_ANY);
742 if (!cp || sz != 5 || memcmp(cp, "more\0\0", 6))
743 tt_abort_msg("Not as expected");
744 tt_uint_op(evbuffer_get_length(evb), ==, 0);
745 evbuffer_validate(evb);
746 s = "\nno newline";
747 evbuffer_add(evb, s, strlen(s));
748 free(cp);
749 evbuffer_validate(evb);
750 cp = evbuffer_readln(evb, &sz, EVBUFFER_EOL_ANY);
751 tt_line_eq("");
752 free(cp);
753 evbuffer_validate(evb);
754 cp = evbuffer_readln(evb, &sz, EVBUFFER_EOL_ANY);
755 tt_assert(!cp);
756 evbuffer_validate(evb);
757 evbuffer_drain(evb, evbuffer_get_length(evb));
758 tt_assert(evbuffer_get_length(evb) == 0);
759 evbuffer_validate(evb);
761 /* Test EOL_CRLF */
762 s = "Line with\rin the middle\nLine with good crlf\r\n\nfinal\n";
763 evbuffer_add(evb, s, strlen(s));
764 evbuffer_validate(evb);
765 cp = evbuffer_readln(evb, &sz, EVBUFFER_EOL_CRLF);
766 tt_line_eq("Line with\rin the middle");
767 free(cp);
768 evbuffer_validate(evb);
770 cp = evbuffer_readln(evb, &sz, EVBUFFER_EOL_CRLF);
771 tt_line_eq("Line with good crlf");
772 free(cp);
773 evbuffer_validate(evb);
775 cp = evbuffer_readln(evb, &sz, EVBUFFER_EOL_CRLF);
776 tt_line_eq("");
777 free(cp);
778 evbuffer_validate(evb);
780 cp = evbuffer_readln(evb, &sz, EVBUFFER_EOL_CRLF);
781 tt_line_eq("final");
782 s = "x";
783 evbuffer_validate(evb);
784 evbuffer_add(evb, s, 1);
785 evbuffer_validate(evb);
786 free(cp);
787 cp = evbuffer_readln(evb, &sz, EVBUFFER_EOL_CRLF);
788 tt_assert(!cp);
789 evbuffer_validate(evb);
791 /* Test CRLF_STRICT */
792 s = " and a bad crlf\nand a good one\r\n\r\nMore\r";
793 evbuffer_add(evb, s, strlen(s));
794 evbuffer_validate(evb);
795 cp = evbuffer_readln(evb, &sz, EVBUFFER_EOL_CRLF_STRICT);
796 tt_line_eq("x and a bad crlf\nand a good one");
797 free(cp);
798 evbuffer_validate(evb);
800 cp = evbuffer_readln(evb, &sz, EVBUFFER_EOL_CRLF_STRICT);
801 tt_line_eq("");
802 free(cp);
803 evbuffer_validate(evb);
805 cp = evbuffer_readln(evb, &sz, EVBUFFER_EOL_CRLF_STRICT);
806 tt_assert(!cp);
807 evbuffer_validate(evb);
808 evbuffer_add(evb, "\n", 1);
809 evbuffer_validate(evb);
811 cp = evbuffer_readln(evb, &sz, EVBUFFER_EOL_CRLF_STRICT);
812 tt_line_eq("More");
813 free(cp);
814 tt_assert(evbuffer_get_length(evb) == 0);
815 evbuffer_validate(evb);
817 s = "An internal CR\r is not an eol\r\nNor is a lack of one";
818 evbuffer_add(evb, s, strlen(s));
819 cp = evbuffer_readln(evb, &sz, EVBUFFER_EOL_CRLF_STRICT);
820 tt_line_eq("An internal CR\r is not an eol");
821 free(cp);
822 evbuffer_validate(evb);
824 cp = evbuffer_readln(evb, &sz, EVBUFFER_EOL_CRLF_STRICT);
825 tt_assert(!cp);
826 evbuffer_validate(evb);
828 evbuffer_add(evb, "\r\n", 2);
829 evbuffer_validate(evb);
830 cp = evbuffer_readln(evb, &sz, EVBUFFER_EOL_CRLF_STRICT);
831 tt_line_eq("Nor is a lack of one");
832 free(cp);
833 tt_assert(evbuffer_get_length(evb) == 0);
834 evbuffer_validate(evb);
836 /* Test LF */
837 s = "An\rand a nl\n\nText";
838 evbuffer_add(evb, s, strlen(s));
839 evbuffer_validate(evb);
841 cp = evbuffer_readln(evb, &sz, EVBUFFER_EOL_LF);
842 tt_line_eq("An\rand a nl");
843 free(cp);
844 evbuffer_validate(evb);
846 cp = evbuffer_readln(evb, &sz, EVBUFFER_EOL_LF);
847 tt_line_eq("");
848 free(cp);
849 evbuffer_validate(evb);
851 cp = evbuffer_readln(evb, &sz, EVBUFFER_EOL_LF);
852 tt_assert(!cp);
853 free(cp);
854 evbuffer_add(evb, "\n", 1);
855 evbuffer_validate(evb);
856 cp = evbuffer_readln(evb, &sz, EVBUFFER_EOL_LF);
857 tt_line_eq("Text");
858 free(cp);
859 evbuffer_validate(evb);
861 /* Test CRLF_STRICT - across boundaries*/
862 s = " and a bad crlf\nand a good one\r";
863 evbuffer_add(evb_tmp, s, strlen(s));
864 evbuffer_validate(evb);
865 evbuffer_add_buffer(evb, evb_tmp);
866 evbuffer_validate(evb);
867 s = "\n\r";
868 evbuffer_add(evb_tmp, s, strlen(s));
869 evbuffer_validate(evb);
870 evbuffer_add_buffer(evb, evb_tmp);
871 evbuffer_validate(evb);
872 s = "\nMore\r";
873 evbuffer_add(evb_tmp, s, strlen(s));
874 evbuffer_validate(evb);
875 evbuffer_add_buffer(evb, evb_tmp);
876 evbuffer_validate(evb);
878 cp = evbuffer_readln(evb, &sz, EVBUFFER_EOL_CRLF_STRICT);
879 tt_line_eq(" and a bad crlf\nand a good one");
880 free(cp);
881 evbuffer_validate(evb);
883 cp = evbuffer_readln(evb, &sz, EVBUFFER_EOL_CRLF_STRICT);
884 tt_line_eq("");
885 free(cp);
886 evbuffer_validate(evb);
888 cp = evbuffer_readln(evb, &sz, EVBUFFER_EOL_CRLF_STRICT);
889 tt_assert(!cp);
890 free(cp);
891 evbuffer_validate(evb);
892 evbuffer_add(evb, "\n", 1);
893 evbuffer_validate(evb);
894 cp = evbuffer_readln(evb, &sz, EVBUFFER_EOL_CRLF_STRICT);
895 tt_line_eq("More");
896 free(cp); cp = NULL;
897 evbuffer_validate(evb);
898 tt_assert(evbuffer_get_length(evb) == 0);
900 /* Test memory problem*/
901 s = "one line\ntwo line\nblue line";
902 evbuffer_add(evb_tmp, s, strlen(s));
903 evbuffer_validate(evb);
904 evbuffer_add_buffer(evb, evb_tmp);
905 evbuffer_validate(evb);
907 cp = evbuffer_readln(evb, &sz, EVBUFFER_EOL_LF);
908 tt_line_eq("one line");
909 free(cp); cp = NULL;
910 evbuffer_validate(evb);
912 /* the next call to readline should fail */
913 #ifndef _EVENT_DISABLE_MM_REPLACEMENT
914 event_set_mem_functions(failing_malloc, realloc, free);
915 cp = evbuffer_readln(evb, &sz, EVBUFFER_EOL_LF);
916 tt_assert(cp == NULL);
917 evbuffer_validate(evb);
919 /* now we should get the next line back */
920 event_set_mem_functions(malloc, realloc, free);
921 #endif
922 cp = evbuffer_readln(evb, &sz, EVBUFFER_EOL_LF);
923 tt_line_eq("two line");
924 free(cp); cp = NULL;
925 evbuffer_validate(evb);
927 end:
928 evbuffer_free(evb);
929 evbuffer_free(evb_tmp);
930 if (cp) free(cp);
933 static void
934 test_evbuffer_search_eol(void *ptr)
936 struct evbuffer *buf = evbuffer_new();
937 struct evbuffer_ptr ptr1, ptr2;
938 const char *s;
939 size_t eol_len;
941 s = "string! \r\n\r\nx\n";
942 evbuffer_add(buf, s, strlen(s));
943 eol_len = -1;
944 ptr1 = evbuffer_search_eol(buf, NULL, &eol_len, EVBUFFER_EOL_CRLF);
945 tt_int_op(ptr1.pos, ==, 8);
946 tt_int_op(eol_len, ==, 2);
948 eol_len = -1;
949 ptr2 = evbuffer_search_eol(buf, &ptr1, &eol_len, EVBUFFER_EOL_CRLF);
950 tt_int_op(ptr2.pos, ==, 8);
951 tt_int_op(eol_len, ==, 2);
953 evbuffer_ptr_set(buf, &ptr1, 1, EVBUFFER_PTR_ADD);
954 eol_len = -1;
955 ptr2 = evbuffer_search_eol(buf, &ptr1, &eol_len, EVBUFFER_EOL_CRLF);
956 tt_int_op(ptr2.pos, ==, 9);
957 tt_int_op(eol_len, ==, 1);
959 eol_len = -1;
960 ptr2 = evbuffer_search_eol(buf, &ptr1, &eol_len, EVBUFFER_EOL_CRLF_STRICT);
961 tt_int_op(ptr2.pos, ==, 10);
962 tt_int_op(eol_len, ==, 2);
964 eol_len = -1;
965 ptr1 = evbuffer_search_eol(buf, NULL, &eol_len, EVBUFFER_EOL_LF);
966 tt_int_op(ptr1.pos, ==, 9);
967 tt_int_op(eol_len, ==, 1);
969 eol_len = -1;
970 ptr2 = evbuffer_search_eol(buf, &ptr1, &eol_len, EVBUFFER_EOL_LF);
971 tt_int_op(ptr2.pos, ==, 9);
972 tt_int_op(eol_len, ==, 1);
974 evbuffer_ptr_set(buf, &ptr1, 1, EVBUFFER_PTR_ADD);
975 eol_len = -1;
976 ptr2 = evbuffer_search_eol(buf, &ptr1, &eol_len, EVBUFFER_EOL_LF);
977 tt_int_op(ptr2.pos, ==, 11);
978 tt_int_op(eol_len, ==, 1);
980 end:
981 evbuffer_free(buf);
984 static void
985 test_evbuffer_iterative(void *ptr)
987 struct evbuffer *buf = evbuffer_new();
988 const char *abc = "abcdefghijklmnopqrstvuwxyzabcdefghijklmnopqrstvuwxyzabcdefghijklmnopqrstvuwxyzabcdefghijklmnopqrstvuwxyz";
989 unsigned i, j, sum, n;
991 sum = 0;
992 n = 0;
993 for (i = 0; i < 1000; ++i) {
994 for (j = 1; j < strlen(abc); ++j) {
995 char format[32];
996 evutil_snprintf(format, sizeof(format), "%%%u.%us", j, j);
997 evbuffer_add_printf(buf, fmtcheck(format, "%s"), abc);
999 /* Only check for rep violations every so often.
1000 Walking over the whole list of chains can get
1001 pretty expensive as it gets long.
1003 if ((n % 337) == 0)
1004 evbuffer_validate(buf);
1006 sum += j;
1007 n++;
1010 evbuffer_validate(buf);
1012 tt_uint_op(sum, ==, evbuffer_get_length(buf));
1015 size_t a,w,u;
1016 a=w=u=0;
1017 evbuffer_get_waste(buf, &a, &w, &u);
1018 if (0)
1019 printf("Allocated: %u.\nWasted: %u.\nUsed: %u.",
1020 (unsigned)a, (unsigned)w, (unsigned)u);
1021 tt_assert( ((double)w)/a < .125);
1023 end:
1024 evbuffer_free(buf);
1028 static void
1029 test_evbuffer_find(void *ptr)
1031 u_char* p;
1032 const char* test1 = "1234567890\r\n";
1033 const char* test2 = "1234567890\r";
1034 #define EVBUFFER_INITIAL_LENGTH 256
1035 char test3[EVBUFFER_INITIAL_LENGTH];
1036 unsigned int i;
1037 struct evbuffer * buf = evbuffer_new();
1039 tt_assert(buf);
1041 /* make sure evbuffer_find doesn't match past the end of the buffer */
1042 evbuffer_add(buf, __UNCONST(test1), strlen(test1));
1043 evbuffer_validate(buf);
1044 evbuffer_drain(buf, strlen(test1));
1045 evbuffer_validate(buf);
1046 evbuffer_add(buf, __UNCONST(test2), strlen(test2));
1047 evbuffer_validate(buf);
1048 p = evbuffer_find(buf, __UNCONST("\r\n"), 2);
1049 tt_want(p == NULL);
1052 * drain the buffer and do another find; in r309 this would
1053 * read past the allocated buffer causing a valgrind error.
1055 evbuffer_drain(buf, strlen(test2));
1056 evbuffer_validate(buf);
1057 for (i = 0; i < EVBUFFER_INITIAL_LENGTH; ++i)
1058 test3[i] = 'a';
1059 test3[EVBUFFER_INITIAL_LENGTH - 1] = 'x';
1060 evbuffer_add(buf, (u_char *)test3, EVBUFFER_INITIAL_LENGTH);
1061 evbuffer_validate(buf);
1062 p = evbuffer_find(buf, __UNCONST("xy"), 2);
1063 tt_want(p == NULL);
1065 /* simple test for match at end of allocated buffer */
1066 p = evbuffer_find(buf, __UNCONST("ax"), 2);
1067 tt_assert(p != NULL);
1068 tt_want(strncmp((char*)p, "ax", 2) == 0);
1070 end:
1071 if (buf)
1072 evbuffer_free(buf);
1075 static void
1076 test_evbuffer_ptr_set(void *ptr)
1078 struct evbuffer *buf = evbuffer_new();
1079 struct evbuffer_ptr pos;
1080 struct evbuffer_iovec v[1];
1082 tt_assert(buf);
1084 /* create some chains */
1085 evbuffer_reserve_space(buf, 5000, v, 1);
1086 v[0].iov_len = 5000;
1087 memset(v[0].iov_base, 1, v[0].iov_len);
1088 evbuffer_commit_space(buf, v, 1);
1089 evbuffer_validate(buf);
1091 evbuffer_reserve_space(buf, 4000, v, 1);
1092 v[0].iov_len = 4000;
1093 memset(v[0].iov_base, 2, v[0].iov_len);
1094 evbuffer_commit_space(buf, v, 1);
1096 evbuffer_reserve_space(buf, 3000, v, 1);
1097 v[0].iov_len = 3000;
1098 memset(v[0].iov_base, 3, v[0].iov_len);
1099 evbuffer_commit_space(buf, v, 1);
1100 evbuffer_validate(buf);
1102 tt_int_op(evbuffer_get_length(buf), ==, 12000);
1104 tt_assert(evbuffer_ptr_set(buf, &pos, 13000, EVBUFFER_PTR_SET) == -1);
1105 tt_assert(pos.pos == -1);
1106 tt_assert(evbuffer_ptr_set(buf, &pos, 0, EVBUFFER_PTR_SET) == 0);
1107 tt_assert(pos.pos == 0);
1108 tt_assert(evbuffer_ptr_set(buf, &pos, 13000, EVBUFFER_PTR_ADD) == -1);
1110 tt_assert(evbuffer_ptr_set(buf, &pos, 0, EVBUFFER_PTR_SET) == 0);
1111 tt_assert(pos.pos == 0);
1112 tt_assert(evbuffer_ptr_set(buf, &pos, 10000, EVBUFFER_PTR_ADD) == 0);
1113 tt_assert(pos.pos == 10000);
1114 tt_assert(evbuffer_ptr_set(buf, &pos, 1000, EVBUFFER_PTR_ADD) == 0);
1115 tt_assert(pos.pos == 11000);
1116 tt_assert(evbuffer_ptr_set(buf, &pos, 1000, EVBUFFER_PTR_ADD) == -1);
1117 tt_assert(pos.pos == -1);
1119 end:
1120 if (buf)
1121 evbuffer_free(buf);
1124 static void
1125 test_evbuffer_search(void *ptr)
1127 struct evbuffer *buf = evbuffer_new();
1128 struct evbuffer *tmp = evbuffer_new();
1129 struct evbuffer_ptr pos, end;
1131 tt_assert(buf);
1132 tt_assert(tmp);
1134 /* set up our chains */
1135 evbuffer_add_printf(tmp, "hello"); /* 5 chars */
1136 evbuffer_add_buffer(buf, tmp);
1137 evbuffer_add_printf(tmp, "foo"); /* 3 chars */
1138 evbuffer_add_buffer(buf, tmp);
1139 evbuffer_add_printf(tmp, "cat"); /* 3 chars */
1140 evbuffer_add_buffer(buf, tmp);
1141 evbuffer_add_printf(tmp, "attack");
1142 evbuffer_add_buffer(buf, tmp);
1144 pos = evbuffer_search(buf, "attack", 6, NULL);
1145 tt_int_op(pos.pos, ==, 11);
1146 pos = evbuffer_search(buf, "attacker", 8, NULL);
1147 tt_int_op(pos.pos, ==, -1);
1149 /* test continuing search */
1150 pos = evbuffer_search(buf, "oc", 2, NULL);
1151 tt_int_op(pos.pos, ==, 7);
1152 pos = evbuffer_search(buf, "cat", 3, &pos);
1153 tt_int_op(pos.pos, ==, 8);
1154 pos = evbuffer_search(buf, "tacking", 7, &pos);
1155 tt_int_op(pos.pos, ==, -1);
1157 evbuffer_ptr_set(buf, &pos, 5, EVBUFFER_PTR_SET);
1158 pos = evbuffer_search(buf, "foo", 3, &pos);
1159 tt_int_op(pos.pos, ==, 5);
1161 evbuffer_ptr_set(buf, &pos, 2, EVBUFFER_PTR_ADD);
1162 pos = evbuffer_search(buf, "tat", 3, &pos);
1163 tt_int_op(pos.pos, ==, 10);
1165 /* test bounded search. */
1166 /* Set "end" to the first t in "attack". */
1167 evbuffer_ptr_set(buf, &end, 12, EVBUFFER_PTR_SET);
1168 pos = evbuffer_search_range(buf, "foo", 3, NULL, &end);
1169 tt_int_op(pos.pos, ==, 5);
1170 pos = evbuffer_search_range(buf, "foocata", 7, NULL, &end);
1171 tt_int_op(pos.pos, ==, 5);
1172 pos = evbuffer_search_range(buf, "foocatat", 8, NULL, &end);
1173 tt_int_op(pos.pos, ==, -1);
1174 pos = evbuffer_search_range(buf, "ack", 3, NULL, &end);
1175 tt_int_op(pos.pos, ==, -1);
1178 end:
1179 if (buf)
1180 evbuffer_free(buf);
1181 if (tmp)
1182 evbuffer_free(tmp);
1185 static void
1186 log_change_callback(struct evbuffer *buffer,
1187 const struct evbuffer_cb_info *cbinfo,
1188 void *arg)
1191 size_t old_len = cbinfo->orig_size;
1192 size_t new_len = old_len + cbinfo->n_added - cbinfo->n_deleted;
1193 struct evbuffer *out = arg;
1194 evbuffer_add_printf(out, "%lu->%lu; ", (unsigned long)old_len,
1195 (unsigned long)new_len);
1197 static void
1198 self_draining_callback(struct evbuffer *evbuffer, size_t old_len,
1199 size_t new_len, void *arg)
1201 if (new_len > old_len)
1202 evbuffer_drain(evbuffer, new_len);
1205 static void
1206 test_evbuffer_callbacks(void *ptr)
1208 struct evbuffer *buf = evbuffer_new();
1209 struct evbuffer *buf_out1 = evbuffer_new();
1210 struct evbuffer *buf_out2 = evbuffer_new();
1211 struct evbuffer_cb_entry *cb1, *cb2;
1213 tt_assert(buf);
1214 tt_assert(buf_out1);
1215 tt_assert(buf_out2);
1217 cb1 = evbuffer_add_cb(buf, log_change_callback, buf_out1);
1218 cb2 = evbuffer_add_cb(buf, log_change_callback, buf_out2);
1220 /* Let's run through adding and deleting some stuff from the buffer
1221 * and turning the callbacks on and off and removing them. The callback
1222 * adds a summary of length changes to buf_out1/buf_out2 when called. */
1223 /* size: 0-> 36. */
1224 evbuffer_add_printf(buf, "The %d magic words are spotty pudding", 2);
1225 evbuffer_validate(buf);
1226 evbuffer_cb_clear_flags(buf, cb2, EVBUFFER_CB_ENABLED);
1227 evbuffer_drain(buf, 10); /*36->26*/
1228 evbuffer_validate(buf);
1229 evbuffer_prepend(buf, "Hello", 5);/*26->31*/
1230 evbuffer_cb_set_flags(buf, cb2, EVBUFFER_CB_ENABLED);
1231 evbuffer_add_reference(buf, "Goodbye", 7, NULL, NULL); /*31->38*/
1232 evbuffer_remove_cb_entry(buf, cb1);
1233 evbuffer_validate(buf);
1234 evbuffer_drain(buf, evbuffer_get_length(buf)); /*38->0*/;
1235 tt_assert(-1 == evbuffer_remove_cb(buf, log_change_callback, NULL));
1236 evbuffer_add(buf, "X", 1); /* 0->1 */
1237 tt_assert(!evbuffer_remove_cb(buf, log_change_callback, buf_out2));
1238 evbuffer_validate(buf);
1240 tt_str_op(evbuffer_pullup(buf_out1, -1), ==,
1241 "0->36; 36->26; 26->31; 31->38; ");
1242 tt_str_op(evbuffer_pullup(buf_out2, -1), ==,
1243 "0->36; 31->38; 38->0; 0->1; ");
1244 evbuffer_drain(buf_out1, evbuffer_get_length(buf_out1));
1245 evbuffer_drain(buf_out2, evbuffer_get_length(buf_out2));
1246 /* Let's test the obsolete buffer_setcb function too. */
1247 cb1 = evbuffer_add_cb(buf, log_change_callback, buf_out1);
1248 tt_assert(cb1 != NULL);
1249 cb2 = evbuffer_add_cb(buf, log_change_callback, buf_out2);
1250 tt_assert(cb2 != NULL);
1251 evbuffer_setcb(buf, self_draining_callback, NULL);
1252 evbuffer_add_printf(buf, "This should get drained right away.");
1253 tt_uint_op(evbuffer_get_length(buf), ==, 0);
1254 tt_uint_op(evbuffer_get_length(buf_out1), ==, 0);
1255 tt_uint_op(evbuffer_get_length(buf_out2), ==, 0);
1256 evbuffer_setcb(buf, NULL, NULL);
1257 evbuffer_add_printf(buf, "This will not.");
1258 tt_str_op(evbuffer_pullup(buf, -1), ==, "This will not.");
1259 evbuffer_validate(buf);
1260 evbuffer_drain(buf, evbuffer_get_length(buf));
1261 evbuffer_validate(buf);
1262 #if 0
1263 /* Now let's try a suspended callback. */
1264 cb1 = evbuffer_add_cb(buf, log_change_callback, buf_out1);
1265 cb2 = evbuffer_add_cb(buf, log_change_callback, buf_out2);
1266 evbuffer_cb_suspend(buf,cb2);
1267 evbuffer_prepend(buf,"Hello world",11); /*0->11*/
1268 evbuffer_validate(buf);
1269 evbuffer_cb_suspend(buf,cb1);
1270 evbuffer_add(buf,"more",4); /* 11->15 */
1271 evbuffer_cb_unsuspend(buf,cb2);
1272 evbuffer_drain(buf, 4); /* 15->11 */
1273 evbuffer_cb_unsuspend(buf,cb1);
1274 evbuffer_drain(buf, evbuffer_get_length(buf)); /* 11->0 */
1276 tt_str_op(evbuffer_pullup(buf_out1, -1), ==,
1277 "0->11; 11->11; 11->0; ");
1278 tt_str_op(evbuffer_pullup(buf_out2, -1), ==,
1279 "0->15; 15->11; 11->0; ");
1280 #endif
1282 end:
1283 if (buf)
1284 evbuffer_free(buf);
1285 if (buf_out1)
1286 evbuffer_free(buf_out1);
1287 if (buf_out2)
1288 evbuffer_free(buf_out2);
1291 static int ref_done_cb_called_count = 0;
1292 static void *ref_done_cb_called_with = NULL;
1293 static const void *ref_done_cb_called_with_data = NULL;
1294 static size_t ref_done_cb_called_with_len = 0;
1295 static void ref_done_cb(const void *data, size_t len, void *info)
1297 ++ref_done_cb_called_count;
1298 ref_done_cb_called_with = info;
1299 ref_done_cb_called_with_data = data;
1300 ref_done_cb_called_with_len = len;
1303 static void
1304 test_evbuffer_add_reference(void *ptr)
1306 const char chunk1[] = "If you have found the answer to such a problem";
1307 const char chunk2[] = "you ought to write it up for publication";
1308 /* -- Knuth's "Notes on the Exercises" from TAOCP */
1309 char tmp[16];
1310 size_t len1 = strlen(chunk1), len2=strlen(chunk2);
1312 struct evbuffer *buf1 = NULL, *buf2 = NULL;
1314 buf1 = evbuffer_new();
1315 tt_assert(buf1);
1317 evbuffer_add_reference(buf1, chunk1, len1, ref_done_cb, (void*)111);
1318 evbuffer_add(buf1, ", ", 2);
1319 evbuffer_add_reference(buf1, chunk2, len2, ref_done_cb, (void*)222);
1320 tt_int_op(evbuffer_get_length(buf1), ==, len1+len2+2);
1322 /* Make sure we can drain a little from a reference. */
1323 tt_int_op(evbuffer_remove(buf1, tmp, 6), ==, 6);
1324 tt_int_op(memcmp(tmp, "If you", 6), ==, 0);
1325 tt_int_op(evbuffer_remove(buf1, tmp, 5), ==, 5);
1326 tt_int_op(memcmp(tmp, " have", 5), ==, 0);
1328 /* Make sure that prepending does not meddle with immutable data */
1329 tt_int_op(evbuffer_prepend(buf1, "I have ", 7), ==, 0);
1330 tt_int_op(memcmp(chunk1, "If you", 6), ==, 0);
1331 evbuffer_validate(buf1);
1333 /* Make sure that when the chunk is over, the callback is invoked. */
1334 evbuffer_drain(buf1, 7); /* Remove prepended stuff. */
1335 evbuffer_drain(buf1, len1-11-1); /* remove all but one byte of chunk1 */
1336 tt_int_op(ref_done_cb_called_count, ==, 0);
1337 evbuffer_remove(buf1, tmp, 1);
1338 tt_int_op(tmp[0], ==, 'm');
1339 tt_assert(ref_done_cb_called_with == (void*)111);
1340 tt_assert(ref_done_cb_called_with_data == chunk1);
1341 tt_assert(ref_done_cb_called_with_len == len1);
1342 tt_int_op(ref_done_cb_called_count, ==, 1);
1343 evbuffer_validate(buf1);
1345 /* Drain some of the remaining chunk, then add it to another buffer */
1346 evbuffer_drain(buf1, 6); /* Remove the ", you ". */
1347 buf2 = evbuffer_new();
1348 tt_assert(buf2);
1349 tt_int_op(ref_done_cb_called_count, ==, 1);
1350 evbuffer_add(buf2, "I ", 2);
1352 evbuffer_add_buffer(buf2, buf1);
1353 tt_int_op(ref_done_cb_called_count, ==, 1);
1354 evbuffer_remove(buf2, tmp, 16);
1355 tt_int_op(memcmp("I ought to write", tmp, 16), ==, 0);
1356 evbuffer_drain(buf2, evbuffer_get_length(buf2));
1357 tt_int_op(ref_done_cb_called_count, ==, 2);
1358 tt_assert(ref_done_cb_called_with == (void*)222);
1359 evbuffer_validate(buf2);
1361 /* Now add more stuff to buf1 and make sure that it gets removed on
1362 * free. */
1363 evbuffer_add(buf1, "You shake and shake the ", 24);
1364 evbuffer_add_reference(buf1, "ketchup bottle", 14, ref_done_cb,
1365 (void*)3333);
1366 evbuffer_add(buf1, ". Nothing comes and then a lot'll.", 42);
1367 evbuffer_free(buf1);
1368 buf1 = NULL;
1369 tt_int_op(ref_done_cb_called_count, ==, 3);
1370 tt_assert(ref_done_cb_called_with == (void*)3333);
1372 end:
1373 if (buf1)
1374 evbuffer_free(buf1);
1375 if (buf2)
1376 evbuffer_free(buf2);
1379 /* Some cases that we didn't get in test_evbuffer() above, for more coverage. */
1380 static void
1381 test_evbuffer_prepend(void *ptr)
1383 struct evbuffer *buf1 = NULL, *buf2 = NULL;
1384 char tmp[128];
1385 int n;
1387 buf1 = evbuffer_new();
1388 tt_assert(buf1);
1390 /* Case 0: The evbuffer is entirely empty. */
1391 evbuffer_prepend(buf1, "This string has 29 characters", 29);
1392 evbuffer_validate(buf1);
1394 /* Case 1: Prepend goes entirely in new chunk. */
1395 evbuffer_prepend(buf1, "Short.", 6);
1396 evbuffer_validate(buf1);
1398 /* Case 2: prepend goes entirely in first chunk. */
1399 evbuffer_drain(buf1, 6+11);
1400 evbuffer_prepend(buf1, "it", 2);
1401 evbuffer_validate(buf1);
1402 tt_assert(!memcmp(buf1->first->buffer+buf1->first->misalign,
1403 "it has", 6));
1405 /* Case 3: prepend is split over multiple chunks. */
1406 evbuffer_prepend(buf1, "It is no longer true to say ", 28);
1407 evbuffer_validate(buf1);
1408 n = evbuffer_remove(buf1, tmp, sizeof(tmp)-1);
1409 tmp[n]='\0';
1410 tt_str_op(tmp,==,"It is no longer true to say it has 29 characters");
1412 buf2 = evbuffer_new();
1413 tt_assert(buf2);
1415 /* Case 4: prepend a buffer to an empty buffer. */
1416 n = 999;
1417 evbuffer_add_printf(buf1, "Here is string %d. ", n++);
1418 evbuffer_prepend_buffer(buf2, buf1);
1419 evbuffer_validate(buf2);
1421 /* Case 5: prepend a buffer to a nonempty buffer. */
1422 evbuffer_add_printf(buf1, "Here is string %d. ", n++);
1423 evbuffer_prepend_buffer(buf2, buf1);
1424 evbuffer_validate(buf2);
1425 evbuffer_validate(buf1);
1426 n = evbuffer_remove(buf2, tmp, sizeof(tmp)-1);
1427 tmp[n]='\0';
1428 tt_str_op(tmp,==,"Here is string 1000. Here is string 999. ");
1430 end:
1431 if (buf1)
1432 evbuffer_free(buf1);
1433 if (buf2)
1434 evbuffer_free(buf2);
1438 static void
1439 test_evbuffer_peek(void *info)
1441 struct evbuffer *buf = NULL, *tmp_buf = NULL;
1442 int i;
1443 struct evbuffer_iovec v[20];
1444 struct evbuffer_ptr ptr;
1446 #define tt_iov_eq(v, s) \
1447 tt_int_op((v)->iov_len, ==, strlen(s)); \
1448 tt_assert(!memcmp((v)->iov_base, (s), strlen(s)))
1450 /* Let's make a very fragmented buffer. */
1451 buf = evbuffer_new();
1452 tmp_buf = evbuffer_new();
1453 for (i = 0; i < 16; ++i) {
1454 evbuffer_add_printf(tmp_buf, "Contents of chunk [%d]\n", i);
1455 evbuffer_add_buffer(buf, tmp_buf);
1458 /* How many chunks do we need for everything? */
1459 i = evbuffer_peek(buf, -1, NULL, NULL, 0);
1460 tt_int_op(i, ==, 16);
1462 /* Simple peek: get everything. */
1463 i = evbuffer_peek(buf, -1, NULL, v, 20);
1464 tt_int_op(i, ==, 16); /* we used only 16 chunks. */
1465 tt_iov_eq(&v[0], "Contents of chunk [0]\n");
1466 tt_iov_eq(&v[3], "Contents of chunk [3]\n");
1467 tt_iov_eq(&v[12], "Contents of chunk [12]\n");
1468 tt_iov_eq(&v[15], "Contents of chunk [15]\n");
1470 /* Just get one chunk worth. */
1471 memset(v, 0, sizeof(v));
1472 i = evbuffer_peek(buf, -1, NULL, v, 1);
1473 tt_int_op(i, ==, 1);
1474 tt_iov_eq(&v[0], "Contents of chunk [0]\n");
1475 tt_assert(v[1].iov_base == NULL);
1477 /* Suppose we want at least the first 40 bytes. */
1478 memset(v, 0, sizeof(v));
1479 i = evbuffer_peek(buf, 40, NULL, v, 16);
1480 tt_int_op(i, ==, 2);
1481 tt_iov_eq(&v[0], "Contents of chunk [0]\n");
1482 tt_iov_eq(&v[1], "Contents of chunk [1]\n");
1483 tt_assert(v[2].iov_base == NULL);
1485 /* How many chunks do we need for 100 bytes? */
1486 memset(v, 0, sizeof(v));
1487 i = evbuffer_peek(buf, 100, NULL, NULL, 0);
1488 tt_int_op(i, ==, 5);
1489 tt_assert(v[0].iov_base == NULL);
1491 /* Now we ask for more bytes than we provide chunks for */
1492 memset(v, 0, sizeof(v));
1493 i = evbuffer_peek(buf, 60, NULL, v, 1);
1494 tt_int_op(i, ==, 3);
1495 tt_iov_eq(&v[0], "Contents of chunk [0]\n");
1496 tt_assert(v[1].iov_base == NULL);
1498 /* Now we ask for more bytes than the buffer has. */
1499 memset(v, 0, sizeof(v));
1500 i = evbuffer_peek(buf, 65536, NULL, v, 20);
1501 tt_int_op(i, ==, 16); /* we used only 16 chunks. */
1502 tt_iov_eq(&v[0], "Contents of chunk [0]\n");
1503 tt_iov_eq(&v[3], "Contents of chunk [3]\n");
1504 tt_iov_eq(&v[12], "Contents of chunk [12]\n");
1505 tt_iov_eq(&v[15], "Contents of chunk [15]\n");
1506 tt_assert(v[16].iov_base == NULL);
1508 /* What happens if we try an empty buffer? */
1509 memset(v, 0, sizeof(v));
1510 i = evbuffer_peek(tmp_buf, -1, NULL, v, 20);
1511 tt_int_op(i, ==, 0);
1512 tt_assert(v[0].iov_base == NULL);
1513 memset(v, 0, sizeof(v));
1514 i = evbuffer_peek(tmp_buf, 50, NULL, v, 20);
1515 tt_int_op(i, ==, 0);
1516 tt_assert(v[0].iov_base == NULL);
1518 /* Okay, now time to have fun with pointers. */
1519 memset(v, 0, sizeof(v));
1520 evbuffer_ptr_set(buf, &ptr, 30, EVBUFFER_PTR_SET);
1521 i = evbuffer_peek(buf, 50, &ptr, v, 20);
1522 tt_int_op(i, ==, 3);
1523 tt_iov_eq(&v[0], " of chunk [1]\n");
1524 tt_iov_eq(&v[1], "Contents of chunk [2]\n");
1525 tt_iov_eq(&v[2], "Contents of chunk [3]\n"); /*more than we asked for*/
1527 /* advance to the start of another chain. */
1528 memset(v, 0, sizeof(v));
1529 evbuffer_ptr_set(buf, &ptr, 14, EVBUFFER_PTR_ADD);
1530 i = evbuffer_peek(buf, 44, &ptr, v, 20);
1531 tt_int_op(i, ==, 2);
1532 tt_iov_eq(&v[0], "Contents of chunk [2]\n");
1533 tt_iov_eq(&v[1], "Contents of chunk [3]\n"); /*more than we asked for*/
1535 end:
1536 if (buf)
1537 evbuffer_free(buf);
1538 if (tmp_buf)
1539 evbuffer_free(tmp_buf);
1542 /* Check whether evbuffer freezing works right. This is called twice,
1543 once with the argument "start" and once with the argument "end".
1544 When we test "start", we freeze the start of an evbuffer and make sure
1545 that modifying the start of the buffer doesn't work. When we test
1546 "end", we freeze the end of an evbuffer and make sure that modifying
1547 the end of the buffer doesn't work.
1549 static void
1550 test_evbuffer_freeze(void *ptr)
1552 struct evbuffer *buf = NULL, *tmp_buf=NULL;
1553 const char string[] = /* Year's End, Richard Wilbur */
1554 "I've known the wind by water banks to shake\n"
1555 "The late leaves down, which frozen where they fell\n"
1556 "And held in ice as dancers in a spell\n"
1557 "Fluttered all winter long into a lake...";
1558 const int start = !strcmp(ptr, "start");
1559 char *cp;
1560 char charbuf[128];
1561 int r;
1562 size_t orig_length;
1563 struct evbuffer_iovec v[1];
1565 if (!start)
1566 tt_str_op(ptr, ==, "end");
1568 buf = evbuffer_new();
1569 tmp_buf = evbuffer_new();
1570 tt_assert(tmp_buf);
1572 evbuffer_add(buf, string, strlen(string));
1573 evbuffer_freeze(buf, start); /* Freeze the start or the end.*/
1575 #define FREEZE_EQ(a, startcase, endcase) \
1576 do { \
1577 if (start) { \
1578 tt_int_op((a), ==, (startcase)); \
1579 } else { \
1580 tt_int_op((a), ==, (endcase)); \
1582 } while (/*CONSTCOND*/0)
1585 orig_length = evbuffer_get_length(buf);
1587 /* These functions all manipulate the end of buf. */
1588 r = evbuffer_add(buf, "abc", 0);
1589 FREEZE_EQ(r, 0, -1);
1590 r = evbuffer_reserve_space(buf, 10, v, 1);
1591 FREEZE_EQ(r, 1, -1);
1592 if (r == 0) {
1593 memset(v[0].iov_base, 'X', 10);
1594 v[0].iov_len = 10;
1596 r = evbuffer_commit_space(buf, v, 1);
1597 FREEZE_EQ(r, 0, -1);
1598 r = evbuffer_add_reference(buf, string, 5, NULL, NULL);
1599 FREEZE_EQ(r, 0, -1);
1600 r = evbuffer_add_printf(buf, "Hello %s", "world");
1601 FREEZE_EQ(r, 11, -1);
1602 /* TODO: test add_buffer, add_file, read */
1604 if (!start)
1605 tt_int_op(orig_length, ==, evbuffer_get_length(buf));
1607 orig_length = evbuffer_get_length(buf);
1609 /* These functions all manipulate the start of buf. */
1610 r = evbuffer_remove(buf, charbuf, 1);
1611 FREEZE_EQ(r, -1, 1);
1612 r = evbuffer_drain(buf, 3);
1613 FREEZE_EQ(r, -1, 0);
1614 r = evbuffer_prepend(buf, "dummy", 5);
1615 FREEZE_EQ(r, -1, 0);
1616 cp = evbuffer_readln(buf, NULL, EVBUFFER_EOL_LF);
1617 FREEZE_EQ(cp==NULL, 1, 0);
1618 if (cp)
1619 free(cp);
1620 /* TODO: Test remove_buffer, add_buffer, write, prepend_buffer */
1622 if (start)
1623 tt_int_op(orig_length, ==, evbuffer_get_length(buf));
1625 end:
1626 if (buf)
1627 evbuffer_free(buf);
1629 if (tmp_buf)
1630 evbuffer_free(tmp_buf);
1633 static void *
1634 setup_passthrough(const struct testcase_t *testcase)
1636 return testcase->setup_data;
1638 static int
1639 cleanup_passthrough(const struct testcase_t *testcase, void *ptr)
1641 (void) ptr;
1642 return 1;
1645 static const struct testcase_setup_t nil_setup = {
1646 setup_passthrough,
1647 cleanup_passthrough
1650 struct testcase_t evbuffer_testcases[] = {
1651 { "evbuffer", test_evbuffer, 0, NULL, NULL },
1652 { "remove_buffer_with_empty", test_evbuffer_remove_buffer_with_empty, 0, NULL, NULL },
1653 { "reserve2", test_evbuffer_reserve2, 0, NULL, NULL },
1654 { "reserve_many", test_evbuffer_reserve_many, 0, NULL, NULL },
1655 { "reserve_many2", test_evbuffer_reserve_many, 0, &nil_setup, __UNCONST("add") },
1656 { "reserve_many3", test_evbuffer_reserve_many, 0, &nil_setup, __UNCONST("fill") },
1657 { "expand", test_evbuffer_expand, 0, NULL, NULL },
1658 { "reference", test_evbuffer_reference, 0, NULL, NULL },
1659 { "iterative", test_evbuffer_iterative, 0, NULL, NULL },
1660 { "readln", test_evbuffer_readln, TT_NO_LOGS, &basic_setup, NULL },
1661 { "search_eol", test_evbuffer_search_eol, 0, NULL, NULL },
1662 { "find", test_evbuffer_find, 0, NULL, NULL },
1663 { "ptr_set", test_evbuffer_ptr_set, 0, NULL, NULL },
1664 { "search", test_evbuffer_search, 0, NULL, NULL },
1665 { "callbacks", test_evbuffer_callbacks, 0, NULL, NULL },
1666 { "add_reference", test_evbuffer_add_reference, 0, NULL, NULL },
1667 { "prepend", test_evbuffer_prepend, TT_FORK, NULL, NULL },
1668 { "peek", test_evbuffer_peek, 0, NULL, NULL },
1669 { "freeze_start", test_evbuffer_freeze, 0, &nil_setup, __UNCONST("start") },
1670 { "freeze_end", test_evbuffer_freeze, 0, &nil_setup, __UNCONST("end") },
1671 /* TODO: need a temp file implementation for Windows */
1672 { "add_file_sendfile", test_evbuffer_add_file, TT_FORK, &nil_setup,
1673 __UNCONST("sendfile") },
1674 { "add_file_mmap", test_evbuffer_add_file, TT_FORK, &nil_setup,
1675 __UNCONST("mmap") },
1676 { "add_file_linear", test_evbuffer_add_file, TT_FORK, &nil_setup,
1677 __UNCONST("linear") },
1679 END_OF_TESTCASES