dnscrypt-proxy update: 1.4.1
[tomato.git] / release / src-rt-6.x.4708 / router / dnscrypt / src / libevent-modified / test / regress_buffer.c
blobd7cc538581491d3581c0f894e6cb7eae48df682b
1 /*
2 * Copyright (c) 2003-2007 Niels Provos <provos@citi.umich.edu>
3 * Copyright (c) 2007-2012 Niels Provos and Nick Mathewson
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. The name of the author may not be used to endorse or promote products
14 * derived from this software without specific prior written permission.
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
17 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
18 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
19 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
20 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
21 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
22 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
23 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
25 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 #ifdef WIN32
29 #include <winsock2.h>
30 #include <windows.h>
31 #endif
33 #include "event2/event-config.h"
35 #include <sys/types.h>
36 #include <sys/stat.h>
37 #ifdef _EVENT_HAVE_SYS_TIME_H
38 #include <sys/time.h>
39 #endif
40 #include <sys/queue.h>
41 #ifndef WIN32
42 #include <sys/socket.h>
43 #include <sys/wait.h>
44 #include <signal.h>
45 #include <unistd.h>
46 #include <netdb.h>
47 #endif
48 #include <stdlib.h>
49 #include <stdio.h>
50 #include <string.h>
51 #include <errno.h>
52 #include <assert.h>
54 #include "event2/event.h"
55 #include "event2/buffer.h"
56 #include "event2/buffer_compat.h"
57 #include "event2/util.h"
59 #include "evbuffer-internal.h"
60 #include "log-internal.h"
62 #include "regress.h"
64 /* Validates that an evbuffer is good. Returns false if it isn't, true if it
65 * is*/
66 static int
67 _evbuffer_validate(struct evbuffer *buf)
69 struct evbuffer_chain *chain;
70 size_t sum = 0;
71 int found_last_with_datap = 0;
73 if (buf->first == NULL) {
74 tt_assert(buf->last == NULL);
75 tt_assert(buf->total_len == 0);
78 chain = buf->first;
80 tt_assert(buf->last_with_datap);
81 if (buf->last_with_datap == &buf->first)
82 found_last_with_datap = 1;
84 while (chain != NULL) {
85 if (&chain->next == buf->last_with_datap)
86 found_last_with_datap = 1;
87 sum += chain->off;
88 if (chain->next == NULL) {
89 tt_assert(buf->last == chain);
91 tt_assert(chain->buffer_len >= chain->misalign + chain->off);
92 chain = chain->next;
95 if (buf->first)
96 tt_assert(*buf->last_with_datap);
98 if (*buf->last_with_datap) {
99 chain = *buf->last_with_datap;
100 if (chain->off == 0 || buf->total_len == 0) {
101 tt_assert(chain->off == 0)
102 tt_assert(chain == buf->first);
103 tt_assert(buf->total_len == 0);
105 chain = chain->next;
106 while (chain != NULL) {
107 tt_assert(chain->off == 0);
108 chain = chain->next;
110 } else {
111 tt_assert(buf->last_with_datap == &buf->first);
113 tt_assert(found_last_with_datap);
115 tt_assert(sum == buf->total_len);
116 return 1;
117 end:
118 return 0;
121 static void
122 evbuffer_get_waste(struct evbuffer *buf, size_t *allocatedp, size_t *wastedp, size_t *usedp)
124 struct evbuffer_chain *chain;
125 size_t a, w, u;
126 int n = 0;
127 u = a = w = 0;
129 chain = buf->first;
130 /* skip empty at start */
131 while (chain && chain->off==0) {
132 ++n;
133 a += chain->buffer_len;
134 chain = chain->next;
136 /* first nonempty chain: stuff at the end only is wasted. */
137 if (chain) {
138 ++n;
139 a += chain->buffer_len;
140 u += chain->off;
141 if (chain->next && chain->next->off)
142 w += (size_t)(chain->buffer_len - (chain->misalign + chain->off));
143 chain = chain->next;
145 /* subsequent nonempty chains */
146 while (chain && chain->off) {
147 ++n;
148 a += chain->buffer_len;
149 w += (size_t)chain->misalign;
150 u += chain->off;
151 if (chain->next && chain->next->off)
152 w += (size_t) (chain->buffer_len - (chain->misalign + chain->off));
153 chain = chain->next;
155 /* subsequent empty chains */
156 while (chain) {
157 ++n;
158 a += chain->buffer_len;
160 *allocatedp = a;
161 *wastedp = w;
162 *usedp = u;
165 #define evbuffer_validate(buf) \
166 TT_STMT_BEGIN if (!_evbuffer_validate(buf)) TT_DIE(("Buffer format invalid")); TT_STMT_END
168 static void
169 test_evbuffer(void *ptr)
171 static char buffer[512], *tmp;
172 struct evbuffer *evb = evbuffer_new();
173 struct evbuffer *evb_two = evbuffer_new();
174 size_t sz_tmp;
175 int i;
177 evbuffer_validate(evb);
178 evbuffer_add_printf(evb, "%s/%d", "hello", 1);
179 evbuffer_validate(evb);
181 tt_assert(evbuffer_get_length(evb) == 7);
182 tt_assert(!memcmp((char*)EVBUFFER_DATA(evb), "hello/1", 1));
184 evbuffer_add_buffer(evb, evb_two);
185 evbuffer_validate(evb);
187 evbuffer_drain(evb, strlen("hello/"));
188 evbuffer_validate(evb);
189 tt_assert(evbuffer_get_length(evb) == 1);
190 tt_assert(!memcmp((char*)EVBUFFER_DATA(evb), "1", 1));
192 evbuffer_add_printf(evb_two, "%s", "/hello");
193 evbuffer_validate(evb);
194 evbuffer_add_buffer(evb, evb_two);
195 evbuffer_validate(evb);
197 tt_assert(evbuffer_get_length(evb_two) == 0);
198 tt_assert(evbuffer_get_length(evb) == 7);
199 tt_assert(!memcmp((char*)EVBUFFER_DATA(evb), "1/hello", 7) != 0);
201 memset(buffer, 0, sizeof(buffer));
202 evbuffer_add(evb, buffer, sizeof(buffer));
203 evbuffer_validate(evb);
204 tt_assert(evbuffer_get_length(evb) == 7 + 512);
206 tmp = (char *)evbuffer_pullup(evb, 7 + 512);
207 tt_assert(tmp);
208 tt_assert(!strncmp(tmp, "1/hello", 7));
209 tt_assert(!memcmp(tmp + 7, buffer, sizeof(buffer)));
210 evbuffer_validate(evb);
212 evbuffer_prepend(evb, "something", 9);
213 evbuffer_validate(evb);
214 evbuffer_prepend(evb, "else", 4);
215 evbuffer_validate(evb);
217 tmp = (char *)evbuffer_pullup(evb, 4 + 9 + 7);
218 tt_assert(!strncmp(tmp, "elsesomething1/hello", 4 + 9 + 7));
219 evbuffer_validate(evb);
221 evbuffer_drain(evb, -1);
222 evbuffer_validate(evb);
223 evbuffer_drain(evb_two, -1);
224 evbuffer_validate(evb);
226 for (i = 0; i < 3; ++i) {
227 evbuffer_add(evb_two, buffer, sizeof(buffer));
228 evbuffer_validate(evb_two);
229 evbuffer_add_buffer(evb, evb_two);
230 evbuffer_validate(evb);
231 evbuffer_validate(evb_two);
234 tt_assert(evbuffer_get_length(evb_two) == 0);
235 tt_assert(evbuffer_get_length(evb) == i * sizeof(buffer));
237 /* test remove buffer */
238 sz_tmp = (size_t)(sizeof(buffer)*2.5);
239 evbuffer_remove_buffer(evb, evb_two, sz_tmp);
240 tt_assert(evbuffer_get_length(evb_two) == sz_tmp);
241 tt_assert(evbuffer_get_length(evb) == sizeof(buffer) / 2);
242 evbuffer_validate(evb);
244 if (memcmp(evbuffer_pullup(
245 evb, -1), buffer, sizeof(buffer) / 2) != 0 ||
246 memcmp(evbuffer_pullup(
247 evb_two, -1), buffer, sizeof(buffer)) != 0)
248 tt_abort_msg("Pullup did not preserve content");
250 evbuffer_validate(evb);
253 /* testing one-vector reserve and commit */
255 struct evbuffer_iovec v[1];
256 char *buf;
257 int i, j, r;
259 for (i = 0; i < 3; ++i) {
260 r = evbuffer_reserve_space(evb, 10000, v, 1);
261 tt_int_op(r, ==, 1);
262 tt_assert(v[0].iov_len >= 10000);
263 tt_assert(v[0].iov_base != NULL);
265 evbuffer_validate(evb);
266 buf = v[0].iov_base;
267 for (j = 0; j < 10000; ++j) {
268 buf[j] = j;
270 evbuffer_validate(evb);
272 tt_int_op(evbuffer_commit_space(evb, v, 1), ==, 0);
273 evbuffer_validate(evb);
275 tt_assert(evbuffer_get_length(evb) >= 10000);
277 evbuffer_drain(evb, j * 5000);
278 evbuffer_validate(evb);
282 end:
283 evbuffer_free(evb);
284 evbuffer_free(evb_two);
287 static void
288 no_cleanup(const void *data, size_t datalen, void *extra)
292 static void
293 test_evbuffer_remove_buffer_with_empty(void *ptr)
295 struct evbuffer *src = evbuffer_new();
296 struct evbuffer *dst = evbuffer_new();
297 char buf[2];
299 evbuffer_validate(src);
300 evbuffer_validate(dst);
302 /* setup the buffers */
303 /* we need more data in src than we will move later */
304 evbuffer_add_reference(src, buf, sizeof(buf), no_cleanup, NULL);
305 evbuffer_add_reference(src, buf, sizeof(buf), no_cleanup, NULL);
306 /* we need one buffer in dst and one empty buffer at the end */
307 evbuffer_add(dst, buf, sizeof(buf));
308 evbuffer_add_reference(dst, buf, 0, no_cleanup, NULL);
310 evbuffer_validate(src);
311 evbuffer_validate(dst);
313 /* move three bytes over */
314 evbuffer_remove_buffer(src, dst, 3);
316 evbuffer_validate(src);
317 evbuffer_validate(dst);
319 end:
320 evbuffer_free(src);
321 evbuffer_free(dst);
324 static void
325 test_evbuffer_reserve2(void *ptr)
327 /* Test the two-vector cases of reserve/commit. */
328 struct evbuffer *buf = evbuffer_new();
329 int n, i;
330 struct evbuffer_iovec v[2];
331 size_t remaining;
332 char *cp, *cp2;
334 /* First chunk will necessarily be one chunk. Use 512 bytes of it.*/
335 n = evbuffer_reserve_space(buf, 1024, v, 2);
336 tt_int_op(n, ==, 1);
337 tt_int_op(evbuffer_get_length(buf), ==, 0);
338 tt_assert(v[0].iov_base != NULL);
339 tt_int_op(v[0].iov_len, >=, 1024);
340 memset(v[0].iov_base, 'X', 512);
341 cp = v[0].iov_base;
342 remaining = v[0].iov_len - 512;
343 v[0].iov_len = 512;
344 evbuffer_validate(buf);
345 tt_int_op(0, ==, evbuffer_commit_space(buf, v, 1));
346 tt_int_op(evbuffer_get_length(buf), ==, 512);
347 evbuffer_validate(buf);
349 /* Ask for another same-chunk request, in an existing chunk. Use 8
350 * bytes of it. */
351 n = evbuffer_reserve_space(buf, 32, v, 2);
352 tt_int_op(n, ==, 1);
353 tt_assert(cp + 512 == v[0].iov_base);
354 tt_int_op(remaining, ==, v[0].iov_len);
355 memset(v[0].iov_base, 'Y', 8);
356 v[0].iov_len = 8;
357 tt_int_op(0, ==, evbuffer_commit_space(buf, v, 1));
358 tt_int_op(evbuffer_get_length(buf), ==, 520);
359 remaining -= 8;
360 evbuffer_validate(buf);
362 /* Now ask for a request that will be split. Use only one byte of it,
363 though. */
364 n = evbuffer_reserve_space(buf, remaining+64, v, 2);
365 tt_int_op(n, ==, 2);
366 tt_assert(cp + 520 == v[0].iov_base);
367 tt_int_op(remaining, ==, v[0].iov_len);
368 tt_assert(v[1].iov_base);
369 tt_assert(v[1].iov_len >= 64);
370 cp2 = v[1].iov_base;
371 memset(v[0].iov_base, 'Z', 1);
372 v[0].iov_len = 1;
373 tt_int_op(0, ==, evbuffer_commit_space(buf, v, 1));
374 tt_int_op(evbuffer_get_length(buf), ==, 521);
375 remaining -= 1;
376 evbuffer_validate(buf);
378 /* Now ask for a request that will be split. Use some of the first
379 * part and some of the second. */
380 n = evbuffer_reserve_space(buf, remaining+64, v, 2);
381 evbuffer_validate(buf);
382 tt_int_op(n, ==, 2);
383 tt_assert(cp + 521 == v[0].iov_base);
384 tt_int_op(remaining, ==, v[0].iov_len);
385 tt_assert(v[1].iov_base == cp2);
386 tt_assert(v[1].iov_len >= 64);
387 memset(v[0].iov_base, 'W', 400);
388 v[0].iov_len = 400;
389 memset(v[1].iov_base, 'x', 60);
390 v[1].iov_len = 60;
391 tt_int_op(0, ==, evbuffer_commit_space(buf, v, 2));
392 tt_int_op(evbuffer_get_length(buf), ==, 981);
393 evbuffer_validate(buf);
395 /* Now peek to make sure stuff got made how we like. */
396 memset(v,0,sizeof(v));
397 n = evbuffer_peek(buf, -1, NULL, v, 2);
398 tt_int_op(n, ==, 2);
399 tt_int_op(v[0].iov_len, ==, 921);
400 tt_int_op(v[1].iov_len, ==, 60);
402 cp = v[0].iov_base;
403 for (i=0; i<512; ++i)
404 tt_int_op(cp[i], ==, 'X');
405 for (i=512; i<520; ++i)
406 tt_int_op(cp[i], ==, 'Y');
407 for (i=520; i<521; ++i)
408 tt_int_op(cp[i], ==, 'Z');
409 for (i=521; i<921; ++i)
410 tt_int_op(cp[i], ==, 'W');
412 cp = v[1].iov_base;
413 for (i=0; i<60; ++i)
414 tt_int_op(cp[i], ==, 'x');
416 end:
417 evbuffer_free(buf);
420 static void
421 test_evbuffer_reserve_many(void *ptr)
423 /* This is a glass-box test to handle expanding a buffer with more
424 * chunks and reallocating chunks as needed */
425 struct evbuffer *buf = evbuffer_new();
426 struct evbuffer_iovec v[8];
427 int n;
428 size_t sz;
429 int add_data = ptr && !strcmp(ptr, "add");
430 int fill_first = ptr && !strcmp(ptr, "fill");
431 char *cp1, *cp2;
433 /* When reserving the the first chunk, we just allocate it */
434 n = evbuffer_reserve_space(buf, 128, v, 2);
435 evbuffer_validate(buf);
436 tt_int_op(n, ==, 1);
437 tt_assert(v[0].iov_len >= 128);
438 sz = v[0].iov_len;
439 cp1 = v[0].iov_base;
440 if (add_data) {
441 *(char*)v[0].iov_base = 'X';
442 v[0].iov_len = 1;
443 n = evbuffer_commit_space(buf, v, 1);
444 tt_int_op(n, ==, 0);
445 } else if (fill_first) {
446 memset(v[0].iov_base, 'X', v[0].iov_len);
447 n = evbuffer_commit_space(buf, v, 1);
448 tt_int_op(n, ==, 0);
449 n = evbuffer_reserve_space(buf, 128, v, 2);
450 tt_int_op(n, ==, 1);
451 sz = v[0].iov_len;
452 tt_assert(v[0].iov_base != cp1);
453 cp1 = v[0].iov_base;
456 /* Make another chunk get added. */
457 n = evbuffer_reserve_space(buf, sz+128, v, 2);
458 evbuffer_validate(buf);
459 tt_int_op(n, ==, 2);
460 sz = v[0].iov_len + v[1].iov_len;
461 tt_int_op(sz, >=, v[0].iov_len+128);
462 if (add_data) {
463 tt_assert(v[0].iov_base == cp1 + 1);
464 } else {
465 tt_assert(v[0].iov_base == cp1);
467 cp1 = v[0].iov_base;
468 cp2 = v[1].iov_base;
470 /* And a third chunk. */
471 n = evbuffer_reserve_space(buf, sz+128, v, 3);
472 evbuffer_validate(buf);
473 tt_int_op(n, ==, 3);
474 tt_assert(cp1 == v[0].iov_base);
475 tt_assert(cp2 == v[1].iov_base);
476 sz = v[0].iov_len + v[1].iov_len + v[2].iov_len;
478 /* Now force a reallocation by asking for more space in only 2
479 * buffers. */
480 n = evbuffer_reserve_space(buf, sz+128, v, 2);
481 evbuffer_validate(buf);
482 if (add_data) {
483 tt_int_op(n, ==, 2);
484 tt_assert(cp1 == v[0].iov_base);
485 } else {
486 tt_int_op(n, ==, 1);
489 end:
490 evbuffer_free(buf);
493 static void
494 test_evbuffer_expand(void *ptr)
496 char data[4096];
497 struct evbuffer *buf;
498 size_t a,w,u;
499 void *buffer;
501 memset(data, 'X', sizeof(data));
503 /* Make sure that expand() works on an empty buffer */
504 buf = evbuffer_new();
505 tt_int_op(evbuffer_expand(buf, 20000), ==, 0);
506 evbuffer_validate(buf);
507 a=w=u=0;
508 evbuffer_get_waste(buf, &a,&w,&u);
509 tt_assert(w == 0);
510 tt_assert(u == 0);
511 tt_assert(a >= 20000);
512 tt_assert(buf->first);
513 tt_assert(buf->first == buf->last);
514 tt_assert(buf->first->off == 0);
515 tt_assert(buf->first->buffer_len >= 20000);
517 /* Make sure that expand() works as a no-op when there's enough
518 * contiguous space already. */
519 buffer = buf->first->buffer;
520 evbuffer_add(buf, data, 1024);
521 tt_int_op(evbuffer_expand(buf, 1024), ==, 0);
522 tt_assert(buf->first->buffer == buffer);
523 evbuffer_validate(buf);
524 evbuffer_free(buf);
526 /* Make sure that expand() can work by moving misaligned data
527 * when it makes sense to do so. */
528 buf = evbuffer_new();
529 evbuffer_add(buf, data, 400);
531 int n = (int)(buf->first->buffer_len - buf->first->off - 1);
532 tt_assert(n < (int)sizeof(data));
533 evbuffer_add(buf, data, n);
535 tt_assert(buf->first == buf->last);
536 tt_assert(buf->first->off == buf->first->buffer_len - 1);
537 evbuffer_drain(buf, buf->first->off - 1);
538 tt_assert(1 == evbuffer_get_length(buf));
539 tt_assert(buf->first->misalign > 0);
540 tt_assert(buf->first->off == 1);
541 buffer = buf->first->buffer;
542 tt_assert(evbuffer_expand(buf, 40) == 0);
543 tt_assert(buf->first == buf->last);
544 tt_assert(buf->first->off == 1);
545 tt_assert(buf->first->buffer == buffer);
546 tt_assert(buf->first->misalign == 0);
547 evbuffer_validate(buf);
548 evbuffer_free(buf);
550 /* add, expand, pull-up: This used to crash libevent. */
551 buf = evbuffer_new();
553 evbuffer_add(buf, data, sizeof(data));
554 evbuffer_add(buf, data, sizeof(data));
555 evbuffer_add(buf, data, sizeof(data));
557 evbuffer_validate(buf);
558 evbuffer_expand(buf, 1024);
559 evbuffer_validate(buf);
560 evbuffer_pullup(buf, -1);
561 evbuffer_validate(buf);
563 end:
564 evbuffer_free(buf);
568 static int reference_cb_called;
569 static void
570 reference_cb(const void *data, size_t len, void *extra)
572 tt_str_op(data, ==, "this is what we add as read-only memory.");
573 tt_int_op(len, ==, strlen(data));
574 tt_want(extra == (void *)0xdeadaffe);
575 ++reference_cb_called;
576 end:
580 static void
581 test_evbuffer_reference(void *ptr)
583 struct evbuffer *src = evbuffer_new();
584 struct evbuffer *dst = evbuffer_new();
585 struct evbuffer_iovec v[1];
586 const char *data = "this is what we add as read-only memory.";
587 reference_cb_called = 0;
589 tt_assert(evbuffer_add_reference(src, data, strlen(data),
590 reference_cb, (void *)0xdeadaffe) != -1);
592 evbuffer_reserve_space(dst, strlen(data), v, 1);
593 tt_assert(evbuffer_remove(src, v[0].iov_base, 10) != -1);
595 evbuffer_validate(src);
596 evbuffer_validate(dst);
598 /* make sure that we don't write data at the beginning */
599 evbuffer_prepend(src, "aaaaa", 5);
600 evbuffer_validate(src);
601 evbuffer_drain(src, 5);
603 tt_assert(evbuffer_remove(src, ((char*)(v[0].iov_base)) + 10,
604 strlen(data) - 10) != -1);
606 v[0].iov_len = strlen(data);
608 evbuffer_commit_space(dst, v, 1);
609 evbuffer_validate(src);
610 evbuffer_validate(dst);
612 tt_int_op(reference_cb_called, ==, 1);
614 tt_assert(!memcmp(evbuffer_pullup(dst, strlen(data)),
615 data, strlen(data)));
616 evbuffer_validate(dst);
618 end:
619 evbuffer_free(dst);
620 evbuffer_free(src);
623 int _evbuffer_testing_use_sendfile(void);
624 int _evbuffer_testing_use_mmap(void);
625 int _evbuffer_testing_use_linear_file_access(void);
627 static void
628 test_evbuffer_add_file(void *ptr)
630 const char *impl = ptr;
631 struct evbuffer *src = evbuffer_new();
632 const char *data = "this is what we add as file system data.";
633 size_t datalen;
634 const char *compare;
635 int fd = -1;
636 evutil_socket_t pair[2] = {-1, -1};
637 int r=0, n_written=0;
639 /* Add a test for a big file. XXXX */
641 tt_assert(impl);
642 if (!strcmp(impl, "sendfile")) {
643 if (!_evbuffer_testing_use_sendfile())
644 tt_skip();
645 TT_BLATHER(("Using sendfile-based implementaion"));
646 } else if (!strcmp(impl, "mmap")) {
647 if (!_evbuffer_testing_use_mmap())
648 tt_skip();
649 TT_BLATHER(("Using mmap-based implementaion"));
650 } else if (!strcmp(impl, "linear")) {
651 if (!_evbuffer_testing_use_linear_file_access())
652 tt_skip();
653 TT_BLATHER(("Using read-based implementaion"));
654 } else {
655 TT_DIE(("Didn't recognize the implementation"));
658 /* Say that it drains to a fd so that we can use sendfile. */
659 evbuffer_set_flags(src, EVBUFFER_FLAG_DRAINS_TO_FD);
661 #if defined(_EVENT_HAVE_SENDFILE) && defined(__sun__) && defined(__svr4__)
662 /* We need to use a pair of AF_INET sockets, since Solaris
663 doesn't support sendfile() over AF_UNIX. */
664 if (evutil_ersatz_socketpair(AF_INET, SOCK_STREAM, 0, pair) == -1)
665 tt_abort_msg("ersatz_socketpair failed");
666 #else
667 if (evutil_socketpair(AF_UNIX, SOCK_STREAM, 0, pair) == -1)
668 tt_abort_msg("socketpair failed");
669 #endif
671 datalen = strlen(data);
672 fd = regress_make_tmpfile(data, datalen);
674 tt_assert(fd != -1);
676 tt_assert(evbuffer_add_file(src, fd, 0, datalen) != -1);
678 evbuffer_validate(src);
680 while (evbuffer_get_length(src) &&
681 (r = evbuffer_write(src, pair[0])) > 0) {
682 evbuffer_validate(src);
683 n_written += r;
685 tt_int_op(r, !=, -1);
686 tt_int_op(n_written, ==, datalen);
688 evbuffer_validate(src);
689 tt_int_op(evbuffer_read(src, pair[1], (int)strlen(data)), ==, datalen);
690 evbuffer_validate(src);
691 compare = (char *)evbuffer_pullup(src, datalen);
692 tt_assert(compare != NULL);
693 if (memcmp(compare, data, datalen))
694 tt_abort_msg("Data from add_file differs.");
696 evbuffer_validate(src);
697 end:
698 if (pair[0] >= 0)
699 evutil_closesocket(pair[0]);
700 if (pair[1] >= 0)
701 evutil_closesocket(pair[1]);
702 evbuffer_free(src);
705 #ifndef _EVENT_DISABLE_MM_REPLACEMENT
706 static void *
707 failing_malloc(size_t how_much)
709 errno = ENOMEM;
710 return NULL;
712 #endif
714 static void
715 test_evbuffer_readln(void *ptr)
717 struct evbuffer *evb = evbuffer_new();
718 struct evbuffer *evb_tmp = evbuffer_new();
719 const char *s;
720 char *cp = NULL;
721 size_t sz;
723 #define tt_line_eq(content) \
724 TT_STMT_BEGIN \
725 if (!cp || sz != strlen(content) || strcmp(cp, content)) { \
726 TT_DIE(("Wanted %s; got %s [%d]", content, cp, (int)sz)); \
728 TT_STMT_END
730 /* Test EOL_ANY. */
731 s = "complex silly newline\r\n\n\r\n\n\rmore\0\n";
732 evbuffer_add(evb, s, strlen(s)+2);
733 evbuffer_validate(evb);
734 cp = evbuffer_readln(evb, &sz, EVBUFFER_EOL_ANY);
735 tt_line_eq("complex silly newline");
736 free(cp);
737 evbuffer_validate(evb);
738 cp = evbuffer_readln(evb, &sz, EVBUFFER_EOL_ANY);
739 if (!cp || sz != 5 || memcmp(cp, "more\0\0", 6))
740 tt_abort_msg("Not as expected");
741 tt_uint_op(evbuffer_get_length(evb), ==, 0);
742 evbuffer_validate(evb);
743 s = "\nno newline";
744 evbuffer_add(evb, s, strlen(s));
745 free(cp);
746 evbuffer_validate(evb);
747 cp = evbuffer_readln(evb, &sz, EVBUFFER_EOL_ANY);
748 tt_line_eq("");
749 free(cp);
750 evbuffer_validate(evb);
751 cp = evbuffer_readln(evb, &sz, EVBUFFER_EOL_ANY);
752 tt_assert(!cp);
753 evbuffer_validate(evb);
754 evbuffer_drain(evb, evbuffer_get_length(evb));
755 tt_assert(evbuffer_get_length(evb) == 0);
756 evbuffer_validate(evb);
758 /* Test EOL_CRLF */
759 s = "Line with\rin the middle\nLine with good crlf\r\n\nfinal\n";
760 evbuffer_add(evb, s, strlen(s));
761 evbuffer_validate(evb);
762 cp = evbuffer_readln(evb, &sz, EVBUFFER_EOL_CRLF);
763 tt_line_eq("Line with\rin the middle");
764 free(cp);
765 evbuffer_validate(evb);
767 cp = evbuffer_readln(evb, &sz, EVBUFFER_EOL_CRLF);
768 tt_line_eq("Line with good crlf");
769 free(cp);
770 evbuffer_validate(evb);
772 cp = evbuffer_readln(evb, &sz, EVBUFFER_EOL_CRLF);
773 tt_line_eq("");
774 free(cp);
775 evbuffer_validate(evb);
777 cp = evbuffer_readln(evb, &sz, EVBUFFER_EOL_CRLF);
778 tt_line_eq("final");
779 s = "x";
780 evbuffer_validate(evb);
781 evbuffer_add(evb, s, 1);
782 evbuffer_validate(evb);
783 free(cp);
784 cp = evbuffer_readln(evb, &sz, EVBUFFER_EOL_CRLF);
785 tt_assert(!cp);
786 evbuffer_validate(evb);
788 /* Test CRLF_STRICT */
789 s = " and a bad crlf\nand a good one\r\n\r\nMore\r";
790 evbuffer_add(evb, s, strlen(s));
791 evbuffer_validate(evb);
792 cp = evbuffer_readln(evb, &sz, EVBUFFER_EOL_CRLF_STRICT);
793 tt_line_eq("x and a bad crlf\nand a good one");
794 free(cp);
795 evbuffer_validate(evb);
797 cp = evbuffer_readln(evb, &sz, EVBUFFER_EOL_CRLF_STRICT);
798 tt_line_eq("");
799 free(cp);
800 evbuffer_validate(evb);
802 cp = evbuffer_readln(evb, &sz, EVBUFFER_EOL_CRLF_STRICT);
803 tt_assert(!cp);
804 evbuffer_validate(evb);
805 evbuffer_add(evb, "\n", 1);
806 evbuffer_validate(evb);
808 cp = evbuffer_readln(evb, &sz, EVBUFFER_EOL_CRLF_STRICT);
809 tt_line_eq("More");
810 free(cp);
811 tt_assert(evbuffer_get_length(evb) == 0);
812 evbuffer_validate(evb);
814 s = "An internal CR\r is not an eol\r\nNor is a lack of one";
815 evbuffer_add(evb, s, strlen(s));
816 cp = evbuffer_readln(evb, &sz, EVBUFFER_EOL_CRLF_STRICT);
817 tt_line_eq("An internal CR\r is not an eol");
818 free(cp);
819 evbuffer_validate(evb);
821 cp = evbuffer_readln(evb, &sz, EVBUFFER_EOL_CRLF_STRICT);
822 tt_assert(!cp);
823 evbuffer_validate(evb);
825 evbuffer_add(evb, "\r\n", 2);
826 evbuffer_validate(evb);
827 cp = evbuffer_readln(evb, &sz, EVBUFFER_EOL_CRLF_STRICT);
828 tt_line_eq("Nor is a lack of one");
829 free(cp);
830 tt_assert(evbuffer_get_length(evb) == 0);
831 evbuffer_validate(evb);
833 /* Test LF */
834 s = "An\rand a nl\n\nText";
835 evbuffer_add(evb, s, strlen(s));
836 evbuffer_validate(evb);
838 cp = evbuffer_readln(evb, &sz, EVBUFFER_EOL_LF);
839 tt_line_eq("An\rand a nl");
840 free(cp);
841 evbuffer_validate(evb);
843 cp = evbuffer_readln(evb, &sz, EVBUFFER_EOL_LF);
844 tt_line_eq("");
845 free(cp);
846 evbuffer_validate(evb);
848 cp = evbuffer_readln(evb, &sz, EVBUFFER_EOL_LF);
849 tt_assert(!cp);
850 free(cp);
851 evbuffer_add(evb, "\n", 1);
852 evbuffer_validate(evb);
853 cp = evbuffer_readln(evb, &sz, EVBUFFER_EOL_LF);
854 tt_line_eq("Text");
855 free(cp);
856 evbuffer_validate(evb);
858 /* Test CRLF_STRICT - across boundaries*/
859 s = " and a bad crlf\nand a good one\r";
860 evbuffer_add(evb_tmp, s, strlen(s));
861 evbuffer_validate(evb);
862 evbuffer_add_buffer(evb, evb_tmp);
863 evbuffer_validate(evb);
864 s = "\n\r";
865 evbuffer_add(evb_tmp, s, strlen(s));
866 evbuffer_validate(evb);
867 evbuffer_add_buffer(evb, evb_tmp);
868 evbuffer_validate(evb);
869 s = "\nMore\r";
870 evbuffer_add(evb_tmp, s, strlen(s));
871 evbuffer_validate(evb);
872 evbuffer_add_buffer(evb, evb_tmp);
873 evbuffer_validate(evb);
875 cp = evbuffer_readln(evb, &sz, EVBUFFER_EOL_CRLF_STRICT);
876 tt_line_eq(" and a bad crlf\nand a good one");
877 free(cp);
878 evbuffer_validate(evb);
880 cp = evbuffer_readln(evb, &sz, EVBUFFER_EOL_CRLF_STRICT);
881 tt_line_eq("");
882 free(cp);
883 evbuffer_validate(evb);
885 cp = evbuffer_readln(evb, &sz, EVBUFFER_EOL_CRLF_STRICT);
886 tt_assert(!cp);
887 free(cp);
888 evbuffer_validate(evb);
889 evbuffer_add(evb, "\n", 1);
890 evbuffer_validate(evb);
891 cp = evbuffer_readln(evb, &sz, EVBUFFER_EOL_CRLF_STRICT);
892 tt_line_eq("More");
893 free(cp); cp = NULL;
894 evbuffer_validate(evb);
895 tt_assert(evbuffer_get_length(evb) == 0);
897 /* Test memory problem*/
898 s = "one line\ntwo line\nblue line";
899 evbuffer_add(evb_tmp, s, strlen(s));
900 evbuffer_validate(evb);
901 evbuffer_add_buffer(evb, evb_tmp);
902 evbuffer_validate(evb);
904 cp = evbuffer_readln(evb, &sz, EVBUFFER_EOL_LF);
905 tt_line_eq("one line");
906 free(cp); cp = NULL;
907 evbuffer_validate(evb);
909 /* the next call to readline should fail */
910 #ifndef _EVENT_DISABLE_MM_REPLACEMENT
911 event_set_mem_functions(failing_malloc, realloc, free);
912 cp = evbuffer_readln(evb, &sz, EVBUFFER_EOL_LF);
913 tt_assert(cp == NULL);
914 evbuffer_validate(evb);
916 /* now we should get the next line back */
917 event_set_mem_functions(malloc, realloc, free);
918 #endif
919 cp = evbuffer_readln(evb, &sz, EVBUFFER_EOL_LF);
920 tt_line_eq("two line");
921 free(cp); cp = NULL;
922 evbuffer_validate(evb);
924 end:
925 evbuffer_free(evb);
926 evbuffer_free(evb_tmp);
927 if (cp) free(cp);
930 static void
931 test_evbuffer_search_eol(void *ptr)
933 struct evbuffer *buf = evbuffer_new();
934 struct evbuffer_ptr ptr1, ptr2;
935 const char *s;
936 size_t eol_len;
938 s = "string! \r\n\r\nx\n";
939 evbuffer_add(buf, s, strlen(s));
940 eol_len = -1;
941 ptr1 = evbuffer_search_eol(buf, NULL, &eol_len, EVBUFFER_EOL_CRLF);
942 tt_int_op(ptr1.pos, ==, 8);
943 tt_int_op(eol_len, ==, 2);
945 eol_len = -1;
946 ptr2 = evbuffer_search_eol(buf, &ptr1, &eol_len, EVBUFFER_EOL_CRLF);
947 tt_int_op(ptr2.pos, ==, 8);
948 tt_int_op(eol_len, ==, 2);
950 evbuffer_ptr_set(buf, &ptr1, 1, EVBUFFER_PTR_ADD);
951 eol_len = -1;
952 ptr2 = evbuffer_search_eol(buf, &ptr1, &eol_len, EVBUFFER_EOL_CRLF);
953 tt_int_op(ptr2.pos, ==, 9);
954 tt_int_op(eol_len, ==, 1);
956 eol_len = -1;
957 ptr2 = evbuffer_search_eol(buf, &ptr1, &eol_len, EVBUFFER_EOL_CRLF_STRICT);
958 tt_int_op(ptr2.pos, ==, 10);
959 tt_int_op(eol_len, ==, 2);
961 eol_len = -1;
962 ptr1 = evbuffer_search_eol(buf, NULL, &eol_len, EVBUFFER_EOL_LF);
963 tt_int_op(ptr1.pos, ==, 9);
964 tt_int_op(eol_len, ==, 1);
966 eol_len = -1;
967 ptr2 = evbuffer_search_eol(buf, &ptr1, &eol_len, EVBUFFER_EOL_LF);
968 tt_int_op(ptr2.pos, ==, 9);
969 tt_int_op(eol_len, ==, 1);
971 evbuffer_ptr_set(buf, &ptr1, 1, EVBUFFER_PTR_ADD);
972 eol_len = -1;
973 ptr2 = evbuffer_search_eol(buf, &ptr1, &eol_len, EVBUFFER_EOL_LF);
974 tt_int_op(ptr2.pos, ==, 11);
975 tt_int_op(eol_len, ==, 1);
977 end:
978 evbuffer_free(buf);
981 static void
982 test_evbuffer_iterative(void *ptr)
984 struct evbuffer *buf = evbuffer_new();
985 const char *abc = "abcdefghijklmnopqrstvuwxyzabcdefghijklmnopqrstvuwxyzabcdefghijklmnopqrstvuwxyzabcdefghijklmnopqrstvuwxyz";
986 unsigned i, j, sum, n;
988 sum = 0;
989 n = 0;
990 for (i = 0; i < 1000; ++i) {
991 for (j = 1; j < strlen(abc); ++j) {
992 char format[32];
993 evutil_snprintf(format, sizeof(format), "%%%u.%us", j, j);
994 evbuffer_add_printf(buf, format, abc);
996 /* Only check for rep violations every so often.
997 Walking over the whole list of chains can get
998 pretty expensive as it gets long.
1000 if ((n % 337) == 0)
1001 evbuffer_validate(buf);
1003 sum += j;
1004 n++;
1007 evbuffer_validate(buf);
1009 tt_uint_op(sum, ==, evbuffer_get_length(buf));
1012 size_t a,w,u;
1013 a=w=u=0;
1014 evbuffer_get_waste(buf, &a, &w, &u);
1015 if (0)
1016 printf("Allocated: %u.\nWasted: %u.\nUsed: %u.",
1017 (unsigned)a, (unsigned)w, (unsigned)u);
1018 tt_assert( ((double)w)/a < .125);
1020 end:
1021 evbuffer_free(buf);
1025 static void
1026 test_evbuffer_find(void *ptr)
1028 u_char* p;
1029 const char* test1 = "1234567890\r\n";
1030 const char* test2 = "1234567890\r";
1031 #define EVBUFFER_INITIAL_LENGTH 256
1032 char test3[EVBUFFER_INITIAL_LENGTH];
1033 unsigned int i;
1034 struct evbuffer * buf = evbuffer_new();
1036 tt_assert(buf);
1038 /* make sure evbuffer_find doesn't match past the end of the buffer */
1039 evbuffer_add(buf, (u_char*)test1, strlen(test1));
1040 evbuffer_validate(buf);
1041 evbuffer_drain(buf, strlen(test1));
1042 evbuffer_validate(buf);
1043 evbuffer_add(buf, (u_char*)test2, strlen(test2));
1044 evbuffer_validate(buf);
1045 p = evbuffer_find(buf, (u_char*)"\r\n", 2);
1046 tt_want(p == NULL);
1049 * drain the buffer and do another find; in r309 this would
1050 * read past the allocated buffer causing a valgrind error.
1052 evbuffer_drain(buf, strlen(test2));
1053 evbuffer_validate(buf);
1054 for (i = 0; i < EVBUFFER_INITIAL_LENGTH; ++i)
1055 test3[i] = 'a';
1056 test3[EVBUFFER_INITIAL_LENGTH - 1] = 'x';
1057 evbuffer_add(buf, (u_char *)test3, EVBUFFER_INITIAL_LENGTH);
1058 evbuffer_validate(buf);
1059 p = evbuffer_find(buf, (u_char *)"xy", 2);
1060 tt_want(p == NULL);
1062 /* simple test for match at end of allocated buffer */
1063 p = evbuffer_find(buf, (u_char *)"ax", 2);
1064 tt_assert(p != NULL);
1065 tt_want(strncmp((char*)p, "ax", 2) == 0);
1067 end:
1068 if (buf)
1069 evbuffer_free(buf);
1072 static void
1073 test_evbuffer_ptr_set(void *ptr)
1075 struct evbuffer *buf = evbuffer_new();
1076 struct evbuffer_ptr pos;
1077 struct evbuffer_iovec v[1];
1079 tt_assert(buf);
1081 /* create some chains */
1082 evbuffer_reserve_space(buf, 5000, v, 1);
1083 v[0].iov_len = 5000;
1084 memset(v[0].iov_base, 1, v[0].iov_len);
1085 evbuffer_commit_space(buf, v, 1);
1086 evbuffer_validate(buf);
1088 evbuffer_reserve_space(buf, 4000, v, 1);
1089 v[0].iov_len = 4000;
1090 memset(v[0].iov_base, 2, v[0].iov_len);
1091 evbuffer_commit_space(buf, v, 1);
1093 evbuffer_reserve_space(buf, 3000, v, 1);
1094 v[0].iov_len = 3000;
1095 memset(v[0].iov_base, 3, v[0].iov_len);
1096 evbuffer_commit_space(buf, v, 1);
1097 evbuffer_validate(buf);
1099 tt_int_op(evbuffer_get_length(buf), ==, 12000);
1101 tt_assert(evbuffer_ptr_set(buf, &pos, 13000, EVBUFFER_PTR_SET) == -1);
1102 tt_assert(pos.pos == -1);
1103 tt_assert(evbuffer_ptr_set(buf, &pos, 0, EVBUFFER_PTR_SET) == 0);
1104 tt_assert(pos.pos == 0);
1105 tt_assert(evbuffer_ptr_set(buf, &pos, 13000, EVBUFFER_PTR_ADD) == -1);
1107 tt_assert(evbuffer_ptr_set(buf, &pos, 0, EVBUFFER_PTR_SET) == 0);
1108 tt_assert(pos.pos == 0);
1109 tt_assert(evbuffer_ptr_set(buf, &pos, 10000, EVBUFFER_PTR_ADD) == 0);
1110 tt_assert(pos.pos == 10000);
1111 tt_assert(evbuffer_ptr_set(buf, &pos, 1000, EVBUFFER_PTR_ADD) == 0);
1112 tt_assert(pos.pos == 11000);
1113 tt_assert(evbuffer_ptr_set(buf, &pos, 1000, EVBUFFER_PTR_ADD) == -1);
1114 tt_assert(pos.pos == -1);
1116 end:
1117 if (buf)
1118 evbuffer_free(buf);
1121 static void
1122 test_evbuffer_search(void *ptr)
1124 struct evbuffer *buf = evbuffer_new();
1125 struct evbuffer *tmp = evbuffer_new();
1126 struct evbuffer_ptr pos, end;
1128 tt_assert(buf);
1129 tt_assert(tmp);
1131 /* set up our chains */
1132 evbuffer_add_printf(tmp, "hello"); /* 5 chars */
1133 evbuffer_add_buffer(buf, tmp);
1134 evbuffer_add_printf(tmp, "foo"); /* 3 chars */
1135 evbuffer_add_buffer(buf, tmp);
1136 evbuffer_add_printf(tmp, "cat"); /* 3 chars */
1137 evbuffer_add_buffer(buf, tmp);
1138 evbuffer_add_printf(tmp, "attack");
1139 evbuffer_add_buffer(buf, tmp);
1141 pos = evbuffer_search(buf, "attack", 6, NULL);
1142 tt_int_op(pos.pos, ==, 11);
1143 pos = evbuffer_search(buf, "attacker", 8, NULL);
1144 tt_int_op(pos.pos, ==, -1);
1146 /* test continuing search */
1147 pos = evbuffer_search(buf, "oc", 2, NULL);
1148 tt_int_op(pos.pos, ==, 7);
1149 pos = evbuffer_search(buf, "cat", 3, &pos);
1150 tt_int_op(pos.pos, ==, 8);
1151 pos = evbuffer_search(buf, "tacking", 7, &pos);
1152 tt_int_op(pos.pos, ==, -1);
1154 evbuffer_ptr_set(buf, &pos, 5, EVBUFFER_PTR_SET);
1155 pos = evbuffer_search(buf, "foo", 3, &pos);
1156 tt_int_op(pos.pos, ==, 5);
1158 evbuffer_ptr_set(buf, &pos, 2, EVBUFFER_PTR_ADD);
1159 pos = evbuffer_search(buf, "tat", 3, &pos);
1160 tt_int_op(pos.pos, ==, 10);
1162 /* test bounded search. */
1163 /* Set "end" to the first t in "attack". */
1164 evbuffer_ptr_set(buf, &end, 12, EVBUFFER_PTR_SET);
1165 pos = evbuffer_search_range(buf, "foo", 3, NULL, &end);
1166 tt_int_op(pos.pos, ==, 5);
1167 pos = evbuffer_search_range(buf, "foocata", 7, NULL, &end);
1168 tt_int_op(pos.pos, ==, 5);
1169 pos = evbuffer_search_range(buf, "foocatat", 8, NULL, &end);
1170 tt_int_op(pos.pos, ==, -1);
1171 pos = evbuffer_search_range(buf, "ack", 3, NULL, &end);
1172 tt_int_op(pos.pos, ==, -1);
1175 end:
1176 if (buf)
1177 evbuffer_free(buf);
1178 if (tmp)
1179 evbuffer_free(tmp);
1182 static void
1183 log_change_callback(struct evbuffer *buffer,
1184 const struct evbuffer_cb_info *cbinfo,
1185 void *arg)
1188 size_t old_len = cbinfo->orig_size;
1189 size_t new_len = old_len + cbinfo->n_added - cbinfo->n_deleted;
1190 struct evbuffer *out = arg;
1191 evbuffer_add_printf(out, "%lu->%lu; ", (unsigned long)old_len,
1192 (unsigned long)new_len);
1194 static void
1195 self_draining_callback(struct evbuffer *evbuffer, size_t old_len,
1196 size_t new_len, void *arg)
1198 if (new_len > old_len)
1199 evbuffer_drain(evbuffer, new_len);
1202 static void
1203 test_evbuffer_callbacks(void *ptr)
1205 struct evbuffer *buf = evbuffer_new();
1206 struct evbuffer *buf_out1 = evbuffer_new();
1207 struct evbuffer *buf_out2 = evbuffer_new();
1208 struct evbuffer_cb_entry *cb1, *cb2;
1210 tt_assert(buf);
1211 tt_assert(buf_out1);
1212 tt_assert(buf_out2);
1214 cb1 = evbuffer_add_cb(buf, log_change_callback, buf_out1);
1215 cb2 = evbuffer_add_cb(buf, log_change_callback, buf_out2);
1217 /* Let's run through adding and deleting some stuff from the buffer
1218 * and turning the callbacks on and off and removing them. The callback
1219 * adds a summary of length changes to buf_out1/buf_out2 when called. */
1220 /* size: 0-> 36. */
1221 evbuffer_add_printf(buf, "The %d magic words are spotty pudding", 2);
1222 evbuffer_validate(buf);
1223 evbuffer_cb_clear_flags(buf, cb2, EVBUFFER_CB_ENABLED);
1224 evbuffer_drain(buf, 10); /*36->26*/
1225 evbuffer_validate(buf);
1226 evbuffer_prepend(buf, "Hello", 5);/*26->31*/
1227 evbuffer_cb_set_flags(buf, cb2, EVBUFFER_CB_ENABLED);
1228 evbuffer_add_reference(buf, "Goodbye", 7, NULL, NULL); /*31->38*/
1229 evbuffer_remove_cb_entry(buf, cb1);
1230 evbuffer_validate(buf);
1231 evbuffer_drain(buf, evbuffer_get_length(buf)); /*38->0*/;
1232 tt_assert(-1 == evbuffer_remove_cb(buf, log_change_callback, NULL));
1233 evbuffer_add(buf, "X", 1); /* 0->1 */
1234 tt_assert(!evbuffer_remove_cb(buf, log_change_callback, buf_out2));
1235 evbuffer_validate(buf);
1237 tt_str_op(evbuffer_pullup(buf_out1, -1), ==,
1238 "0->36; 36->26; 26->31; 31->38; ");
1239 tt_str_op(evbuffer_pullup(buf_out2, -1), ==,
1240 "0->36; 31->38; 38->0; 0->1; ");
1241 evbuffer_drain(buf_out1, evbuffer_get_length(buf_out1));
1242 evbuffer_drain(buf_out2, evbuffer_get_length(buf_out2));
1243 /* Let's test the obsolete buffer_setcb function too. */
1244 cb1 = evbuffer_add_cb(buf, log_change_callback, buf_out1);
1245 tt_assert(cb1 != NULL);
1246 cb2 = evbuffer_add_cb(buf, log_change_callback, buf_out2);
1247 tt_assert(cb2 != NULL);
1248 evbuffer_setcb(buf, self_draining_callback, NULL);
1249 evbuffer_add_printf(buf, "This should get drained right away.");
1250 tt_uint_op(evbuffer_get_length(buf), ==, 0);
1251 tt_uint_op(evbuffer_get_length(buf_out1), ==, 0);
1252 tt_uint_op(evbuffer_get_length(buf_out2), ==, 0);
1253 evbuffer_setcb(buf, NULL, NULL);
1254 evbuffer_add_printf(buf, "This will not.");
1255 tt_str_op(evbuffer_pullup(buf, -1), ==, "This will not.");
1256 evbuffer_validate(buf);
1257 evbuffer_drain(buf, evbuffer_get_length(buf));
1258 evbuffer_validate(buf);
1259 #if 0
1260 /* Now let's try a suspended callback. */
1261 cb1 = evbuffer_add_cb(buf, log_change_callback, buf_out1);
1262 cb2 = evbuffer_add_cb(buf, log_change_callback, buf_out2);
1263 evbuffer_cb_suspend(buf,cb2);
1264 evbuffer_prepend(buf,"Hello world",11); /*0->11*/
1265 evbuffer_validate(buf);
1266 evbuffer_cb_suspend(buf,cb1);
1267 evbuffer_add(buf,"more",4); /* 11->15 */
1268 evbuffer_cb_unsuspend(buf,cb2);
1269 evbuffer_drain(buf, 4); /* 15->11 */
1270 evbuffer_cb_unsuspend(buf,cb1);
1271 evbuffer_drain(buf, evbuffer_get_length(buf)); /* 11->0 */
1273 tt_str_op(evbuffer_pullup(buf_out1, -1), ==,
1274 "0->11; 11->11; 11->0; ");
1275 tt_str_op(evbuffer_pullup(buf_out2, -1), ==,
1276 "0->15; 15->11; 11->0; ");
1277 #endif
1279 end:
1280 if (buf)
1281 evbuffer_free(buf);
1282 if (buf_out1)
1283 evbuffer_free(buf_out1);
1284 if (buf_out2)
1285 evbuffer_free(buf_out2);
1288 static int ref_done_cb_called_count = 0;
1289 static void *ref_done_cb_called_with = NULL;
1290 static const void *ref_done_cb_called_with_data = NULL;
1291 static size_t ref_done_cb_called_with_len = 0;
1292 static void ref_done_cb(const void *data, size_t len, void *info)
1294 ++ref_done_cb_called_count;
1295 ref_done_cb_called_with = info;
1296 ref_done_cb_called_with_data = data;
1297 ref_done_cb_called_with_len = len;
1300 static void
1301 test_evbuffer_add_reference(void *ptr)
1303 const char chunk1[] = "If you have found the answer to such a problem";
1304 const char chunk2[] = "you ought to write it up for publication";
1305 /* -- Knuth's "Notes on the Exercises" from TAOCP */
1306 char tmp[16];
1307 size_t len1 = strlen(chunk1), len2=strlen(chunk2);
1309 struct evbuffer *buf1 = NULL, *buf2 = NULL;
1311 buf1 = evbuffer_new();
1312 tt_assert(buf1);
1314 evbuffer_add_reference(buf1, chunk1, len1, ref_done_cb, (void*)111);
1315 evbuffer_add(buf1, ", ", 2);
1316 evbuffer_add_reference(buf1, chunk2, len2, ref_done_cb, (void*)222);
1317 tt_int_op(evbuffer_get_length(buf1), ==, len1+len2+2);
1319 /* Make sure we can drain a little from a reference. */
1320 tt_int_op(evbuffer_remove(buf1, tmp, 6), ==, 6);
1321 tt_int_op(memcmp(tmp, "If you", 6), ==, 0);
1322 tt_int_op(evbuffer_remove(buf1, tmp, 5), ==, 5);
1323 tt_int_op(memcmp(tmp, " have", 5), ==, 0);
1325 /* Make sure that prepending does not meddle with immutable data */
1326 tt_int_op(evbuffer_prepend(buf1, "I have ", 7), ==, 0);
1327 tt_int_op(memcmp(chunk1, "If you", 6), ==, 0);
1328 evbuffer_validate(buf1);
1330 /* Make sure that when the chunk is over, the callback is invoked. */
1331 evbuffer_drain(buf1, 7); /* Remove prepended stuff. */
1332 evbuffer_drain(buf1, len1-11-1); /* remove all but one byte of chunk1 */
1333 tt_int_op(ref_done_cb_called_count, ==, 0);
1334 evbuffer_remove(buf1, tmp, 1);
1335 tt_int_op(tmp[0], ==, 'm');
1336 tt_assert(ref_done_cb_called_with == (void*)111);
1337 tt_assert(ref_done_cb_called_with_data == chunk1);
1338 tt_assert(ref_done_cb_called_with_len == len1);
1339 tt_int_op(ref_done_cb_called_count, ==, 1);
1340 evbuffer_validate(buf1);
1342 /* Drain some of the remaining chunk, then add it to another buffer */
1343 evbuffer_drain(buf1, 6); /* Remove the ", you ". */
1344 buf2 = evbuffer_new();
1345 tt_assert(buf2);
1346 tt_int_op(ref_done_cb_called_count, ==, 1);
1347 evbuffer_add(buf2, "I ", 2);
1349 evbuffer_add_buffer(buf2, buf1);
1350 tt_int_op(ref_done_cb_called_count, ==, 1);
1351 evbuffer_remove(buf2, tmp, 16);
1352 tt_int_op(memcmp("I ought to write", tmp, 16), ==, 0);
1353 evbuffer_drain(buf2, evbuffer_get_length(buf2));
1354 tt_int_op(ref_done_cb_called_count, ==, 2);
1355 tt_assert(ref_done_cb_called_with == (void*)222);
1356 evbuffer_validate(buf2);
1358 /* Now add more stuff to buf1 and make sure that it gets removed on
1359 * free. */
1360 evbuffer_add(buf1, "You shake and shake the ", 24);
1361 evbuffer_add_reference(buf1, "ketchup bottle", 14, ref_done_cb,
1362 (void*)3333);
1363 evbuffer_add(buf1, ". Nothing comes and then a lot'll.", 42);
1364 evbuffer_free(buf1);
1365 buf1 = NULL;
1366 tt_int_op(ref_done_cb_called_count, ==, 3);
1367 tt_assert(ref_done_cb_called_with == (void*)3333);
1369 end:
1370 if (buf1)
1371 evbuffer_free(buf1);
1372 if (buf2)
1373 evbuffer_free(buf2);
1376 /* Some cases that we didn't get in test_evbuffer() above, for more coverage. */
1377 static void
1378 test_evbuffer_prepend(void *ptr)
1380 struct evbuffer *buf1 = NULL, *buf2 = NULL;
1381 char tmp[128];
1382 int n;
1384 buf1 = evbuffer_new();
1385 tt_assert(buf1);
1387 /* Case 0: The evbuffer is entirely empty. */
1388 evbuffer_prepend(buf1, "This string has 29 characters", 29);
1389 evbuffer_validate(buf1);
1391 /* Case 1: Prepend goes entirely in new chunk. */
1392 evbuffer_prepend(buf1, "Short.", 6);
1393 evbuffer_validate(buf1);
1395 /* Case 2: prepend goes entirely in first chunk. */
1396 evbuffer_drain(buf1, 6+11);
1397 evbuffer_prepend(buf1, "it", 2);
1398 evbuffer_validate(buf1);
1399 tt_assert(!memcmp(buf1->first->buffer+buf1->first->misalign,
1400 "it has", 6));
1402 /* Case 3: prepend is split over multiple chunks. */
1403 evbuffer_prepend(buf1, "It is no longer true to say ", 28);
1404 evbuffer_validate(buf1);
1405 n = evbuffer_remove(buf1, tmp, sizeof(tmp)-1);
1406 tmp[n]='\0';
1407 tt_str_op(tmp,==,"It is no longer true to say it has 29 characters");
1409 buf2 = evbuffer_new();
1410 tt_assert(buf2);
1412 /* Case 4: prepend a buffer to an empty buffer. */
1413 n = 999;
1414 evbuffer_add_printf(buf1, "Here is string %d. ", n++);
1415 evbuffer_prepend_buffer(buf2, buf1);
1416 evbuffer_validate(buf2);
1418 /* Case 5: prepend a buffer to a nonempty buffer. */
1419 evbuffer_add_printf(buf1, "Here is string %d. ", n++);
1420 evbuffer_prepend_buffer(buf2, buf1);
1421 evbuffer_validate(buf2);
1422 evbuffer_validate(buf1);
1423 n = evbuffer_remove(buf2, tmp, sizeof(tmp)-1);
1424 tmp[n]='\0';
1425 tt_str_op(tmp,==,"Here is string 1000. Here is string 999. ");
1427 end:
1428 if (buf1)
1429 evbuffer_free(buf1);
1430 if (buf2)
1431 evbuffer_free(buf2);
1435 static void
1436 test_evbuffer_peek(void *info)
1438 struct evbuffer *buf = NULL, *tmp_buf = NULL;
1439 int i;
1440 struct evbuffer_iovec v[20];
1441 struct evbuffer_ptr ptr;
1443 #define tt_iov_eq(v, s) \
1444 tt_int_op((v)->iov_len, ==, strlen(s)); \
1445 tt_assert(!memcmp((v)->iov_base, (s), strlen(s)))
1447 /* Let's make a very fragmented buffer. */
1448 buf = evbuffer_new();
1449 tmp_buf = evbuffer_new();
1450 for (i = 0; i < 16; ++i) {
1451 evbuffer_add_printf(tmp_buf, "Contents of chunk [%d]\n", i);
1452 evbuffer_add_buffer(buf, tmp_buf);
1455 /* How many chunks do we need for everything? */
1456 i = evbuffer_peek(buf, -1, NULL, NULL, 0);
1457 tt_int_op(i, ==, 16);
1459 /* Simple peek: get everything. */
1460 i = evbuffer_peek(buf, -1, NULL, v, 20);
1461 tt_int_op(i, ==, 16); /* we used only 16 chunks. */
1462 tt_iov_eq(&v[0], "Contents of chunk [0]\n");
1463 tt_iov_eq(&v[3], "Contents of chunk [3]\n");
1464 tt_iov_eq(&v[12], "Contents of chunk [12]\n");
1465 tt_iov_eq(&v[15], "Contents of chunk [15]\n");
1467 /* Just get one chunk worth. */
1468 memset(v, 0, sizeof(v));
1469 i = evbuffer_peek(buf, -1, NULL, v, 1);
1470 tt_int_op(i, ==, 1);
1471 tt_iov_eq(&v[0], "Contents of chunk [0]\n");
1472 tt_assert(v[1].iov_base == NULL);
1474 /* Suppose we want at least the first 40 bytes. */
1475 memset(v, 0, sizeof(v));
1476 i = evbuffer_peek(buf, 40, NULL, v, 16);
1477 tt_int_op(i, ==, 2);
1478 tt_iov_eq(&v[0], "Contents of chunk [0]\n");
1479 tt_iov_eq(&v[1], "Contents of chunk [1]\n");
1480 tt_assert(v[2].iov_base == NULL);
1482 /* How many chunks do we need for 100 bytes? */
1483 memset(v, 0, sizeof(v));
1484 i = evbuffer_peek(buf, 100, NULL, NULL, 0);
1485 tt_int_op(i, ==, 5);
1486 tt_assert(v[0].iov_base == NULL);
1488 /* Now we ask for more bytes than we provide chunks for */
1489 memset(v, 0, sizeof(v));
1490 i = evbuffer_peek(buf, 60, NULL, v, 1);
1491 tt_int_op(i, ==, 3);
1492 tt_iov_eq(&v[0], "Contents of chunk [0]\n");
1493 tt_assert(v[1].iov_base == NULL);
1495 /* Now we ask for more bytes than the buffer has. */
1496 memset(v, 0, sizeof(v));
1497 i = evbuffer_peek(buf, 65536, NULL, v, 20);
1498 tt_int_op(i, ==, 16); /* we used only 16 chunks. */
1499 tt_iov_eq(&v[0], "Contents of chunk [0]\n");
1500 tt_iov_eq(&v[3], "Contents of chunk [3]\n");
1501 tt_iov_eq(&v[12], "Contents of chunk [12]\n");
1502 tt_iov_eq(&v[15], "Contents of chunk [15]\n");
1503 tt_assert(v[16].iov_base == NULL);
1505 /* What happens if we try an empty buffer? */
1506 memset(v, 0, sizeof(v));
1507 i = evbuffer_peek(tmp_buf, -1, NULL, v, 20);
1508 tt_int_op(i, ==, 0);
1509 tt_assert(v[0].iov_base == NULL);
1510 memset(v, 0, sizeof(v));
1511 i = evbuffer_peek(tmp_buf, 50, NULL, v, 20);
1512 tt_int_op(i, ==, 0);
1513 tt_assert(v[0].iov_base == NULL);
1515 /* Okay, now time to have fun with pointers. */
1516 memset(v, 0, sizeof(v));
1517 evbuffer_ptr_set(buf, &ptr, 30, EVBUFFER_PTR_SET);
1518 i = evbuffer_peek(buf, 50, &ptr, v, 20);
1519 tt_int_op(i, ==, 3);
1520 tt_iov_eq(&v[0], " of chunk [1]\n");
1521 tt_iov_eq(&v[1], "Contents of chunk [2]\n");
1522 tt_iov_eq(&v[2], "Contents of chunk [3]\n"); /*more than we asked for*/
1524 /* advance to the start of another chain. */
1525 memset(v, 0, sizeof(v));
1526 evbuffer_ptr_set(buf, &ptr, 14, EVBUFFER_PTR_ADD);
1527 i = evbuffer_peek(buf, 44, &ptr, v, 20);
1528 tt_int_op(i, ==, 2);
1529 tt_iov_eq(&v[0], "Contents of chunk [2]\n");
1530 tt_iov_eq(&v[1], "Contents of chunk [3]\n"); /*more than we asked for*/
1532 end:
1533 if (buf)
1534 evbuffer_free(buf);
1535 if (tmp_buf)
1536 evbuffer_free(tmp_buf);
1539 /* Check whether evbuffer freezing works right. This is called twice,
1540 once with the argument "start" and once with the argument "end".
1541 When we test "start", we freeze the start of an evbuffer and make sure
1542 that modifying the start of the buffer doesn't work. When we test
1543 "end", we freeze the end of an evbuffer and make sure that modifying
1544 the end of the buffer doesn't work.
1546 static void
1547 test_evbuffer_freeze(void *ptr)
1549 struct evbuffer *buf = NULL, *tmp_buf=NULL;
1550 const char string[] = /* Year's End, Richard Wilbur */
1551 "I've known the wind by water banks to shake\n"
1552 "The late leaves down, which frozen where they fell\n"
1553 "And held in ice as dancers in a spell\n"
1554 "Fluttered all winter long into a lake...";
1555 const int start = !strcmp(ptr, "start");
1556 char *cp;
1557 char charbuf[128];
1558 int r;
1559 size_t orig_length;
1560 struct evbuffer_iovec v[1];
1562 if (!start)
1563 tt_str_op(ptr, ==, "end");
1565 buf = evbuffer_new();
1566 tmp_buf = evbuffer_new();
1567 tt_assert(tmp_buf);
1569 evbuffer_add(buf, string, strlen(string));
1570 evbuffer_freeze(buf, start); /* Freeze the start or the end.*/
1572 #define FREEZE_EQ(a, startcase, endcase) \
1573 do { \
1574 if (start) { \
1575 tt_int_op((a), ==, (startcase)); \
1576 } else { \
1577 tt_int_op((a), ==, (endcase)); \
1579 } while (0)
1582 orig_length = evbuffer_get_length(buf);
1584 /* These functions all manipulate the end of buf. */
1585 r = evbuffer_add(buf, "abc", 0);
1586 FREEZE_EQ(r, 0, -1);
1587 r = evbuffer_reserve_space(buf, 10, v, 1);
1588 FREEZE_EQ(r, 1, -1);
1589 if (r == 0) {
1590 memset(v[0].iov_base, 'X', 10);
1591 v[0].iov_len = 10;
1593 r = evbuffer_commit_space(buf, v, 1);
1594 FREEZE_EQ(r, 0, -1);
1595 r = evbuffer_add_reference(buf, string, 5, NULL, NULL);
1596 FREEZE_EQ(r, 0, -1);
1597 r = evbuffer_add_printf(buf, "Hello %s", "world");
1598 FREEZE_EQ(r, 11, -1);
1599 /* TODO: test add_buffer, add_file, read */
1601 if (!start)
1602 tt_int_op(orig_length, ==, evbuffer_get_length(buf));
1604 orig_length = evbuffer_get_length(buf);
1606 /* These functions all manipulate the start of buf. */
1607 r = evbuffer_remove(buf, charbuf, 1);
1608 FREEZE_EQ(r, -1, 1);
1609 r = evbuffer_drain(buf, 3);
1610 FREEZE_EQ(r, -1, 0);
1611 r = evbuffer_prepend(buf, "dummy", 5);
1612 FREEZE_EQ(r, -1, 0);
1613 cp = evbuffer_readln(buf, NULL, EVBUFFER_EOL_LF);
1614 FREEZE_EQ(cp==NULL, 1, 0);
1615 if (cp)
1616 free(cp);
1617 /* TODO: Test remove_buffer, add_buffer, write, prepend_buffer */
1619 if (start)
1620 tt_int_op(orig_length, ==, evbuffer_get_length(buf));
1622 end:
1623 if (buf)
1624 evbuffer_free(buf);
1626 if (tmp_buf)
1627 evbuffer_free(tmp_buf);
1630 static void *
1631 setup_passthrough(const struct testcase_t *testcase)
1633 return testcase->setup_data;
1635 static int
1636 cleanup_passthrough(const struct testcase_t *testcase, void *ptr)
1638 (void) ptr;
1639 return 1;
1642 static const struct testcase_setup_t nil_setup = {
1643 setup_passthrough,
1644 cleanup_passthrough
1647 struct testcase_t evbuffer_testcases[] = {
1648 { "evbuffer", test_evbuffer, 0, NULL, NULL },
1649 { "remove_buffer_with_empty", test_evbuffer_remove_buffer_with_empty, 0, NULL, NULL },
1650 { "reserve2", test_evbuffer_reserve2, 0, NULL, NULL },
1651 { "reserve_many", test_evbuffer_reserve_many, 0, NULL, NULL },
1652 { "reserve_many2", test_evbuffer_reserve_many, 0, &nil_setup, (void*)"add" },
1653 { "reserve_many3", test_evbuffer_reserve_many, 0, &nil_setup, (void*)"fill" },
1654 { "expand", test_evbuffer_expand, 0, NULL, NULL },
1655 { "reference", test_evbuffer_reference, 0, NULL, NULL },
1656 { "iterative", test_evbuffer_iterative, 0, NULL, NULL },
1657 { "readln", test_evbuffer_readln, TT_NO_LOGS, &basic_setup, NULL },
1658 { "search_eol", test_evbuffer_search_eol, 0, NULL, NULL },
1659 { "find", test_evbuffer_find, 0, NULL, NULL },
1660 { "ptr_set", test_evbuffer_ptr_set, 0, NULL, NULL },
1661 { "search", test_evbuffer_search, 0, NULL, NULL },
1662 { "callbacks", test_evbuffer_callbacks, 0, NULL, NULL },
1663 { "add_reference", test_evbuffer_add_reference, 0, NULL, NULL },
1664 { "prepend", test_evbuffer_prepend, TT_FORK, NULL, NULL },
1665 { "peek", test_evbuffer_peek, 0, NULL, NULL },
1666 { "freeze_start", test_evbuffer_freeze, 0, &nil_setup, (void*)"start" },
1667 { "freeze_end", test_evbuffer_freeze, 0, &nil_setup, (void*)"end" },
1668 /* TODO: need a temp file implementation for Windows */
1669 { "add_file_sendfile", test_evbuffer_add_file, TT_FORK, &nil_setup,
1670 (void*)"sendfile" },
1671 { "add_file_mmap", test_evbuffer_add_file, TT_FORK, &nil_setup,
1672 (void*)"mmap" },
1673 { "add_file_linear", test_evbuffer_add_file, TT_FORK, &nil_setup,
1674 (void*)"linear" },
1676 END_OF_TESTCASES