]> arthur.barton.de Git - netatalk.git/blob - libevent/test/regress_buffer.c
Add libevent
[netatalk.git] / libevent / test / regress_buffer.c
1 /*
2  * Copyright (c) 2003-2007 Niels Provos <provos@citi.umich.edu>
3  * Copyright (c) 2007-2010 Niels Provos and Nick Mathewson
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  * 3. The name of the author may not be used to endorse or promote products
14  *    derived from this software without specific prior written permission.
15  *
16  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
17  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
18  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
19  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
20  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
21  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
22  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
23  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
25  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26  */
27
28 #ifdef WIN32
29 #include <winsock2.h>
30 #include <windows.h>
31 #endif
32
33 #include "event2/event-config.h"
34
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>
53
54 #include "event2/event.h"
55 #include "event2/buffer.h"
56 #include "event2/buffer_compat.h"
57 #include "event2/util.h"
58
59 #include "evbuffer-internal.h"
60 #include "log-internal.h"
61
62 #include "regress.h"
63
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)
68 {
69         struct evbuffer_chain *chain;
70         size_t sum = 0;
71         int found_last_with_datap = 0;
72
73         if (buf->first == NULL) {
74                 tt_assert(buf->last == NULL);
75                 tt_assert(buf->total_len == 0);
76         }
77
78         chain = buf->first;
79
80         tt_assert(buf->last_with_datap);
81         if (buf->last_with_datap == &buf->first)
82                 found_last_with_datap = 1;
83
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);
90                 }
91                 tt_assert(chain->buffer_len >= chain->misalign + chain->off);
92                 chain = chain->next;
93         }
94
95         if (buf->first)
96                 tt_assert(*buf->last_with_datap);
97
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);
104                 }
105                 chain = chain->next;
106                 while (chain != NULL) {
107                         tt_assert(chain->off == 0);
108                         chain = chain->next;
109                 }
110         } else {
111                 tt_assert(buf->last_with_datap == &buf->first);
112         }
113         tt_assert(found_last_with_datap);
114
115         tt_assert(sum == buf->total_len);
116         return 1;
117  end:
118         return 0;
119 }
120
121 static void
122 evbuffer_get_waste(struct evbuffer *buf, size_t *allocatedp, size_t *wastedp, size_t *usedp)
123 {
124         struct evbuffer_chain *chain;
125         size_t a, w, u;
126         int n = 0;
127         u = a = w = 0;
128
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;
135         }
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;
144         }
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;
154         }
155         /* subsequent empty chains */
156         while (chain) {
157                 ++n;
158                 a += chain->buffer_len;
159         }
160         *allocatedp = a;
161         *wastedp = w;
162         *usedp = u;
163 }
164
165 #define evbuffer_validate(buf)                  \
166         TT_STMT_BEGIN if (!_evbuffer_validate(buf)) TT_DIE(("Buffer format invalid")); TT_STMT_END
167
168 static void
169 test_evbuffer(void *ptr)
170 {
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;
176
177         evbuffer_validate(evb);
178         evbuffer_add_printf(evb, "%s/%d", "hello", 1);
179         evbuffer_validate(evb);
180
181         tt_assert(evbuffer_get_length(evb) == 7);
182         tt_assert(!memcmp((char*)EVBUFFER_DATA(evb), "hello/1", 1));
183
184         evbuffer_add_buffer(evb, evb_two);
185         evbuffer_validate(evb);
186
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));
191
192         evbuffer_add_printf(evb_two, "%s", "/hello");
193         evbuffer_validate(evb);
194         evbuffer_add_buffer(evb, evb_two);
195         evbuffer_validate(evb);
196
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);
200
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);
205
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);
211
212         evbuffer_prepend(evb, "something", 9);
213         evbuffer_validate(evb);
214         evbuffer_prepend(evb, "else", 4);
215         evbuffer_validate(evb);
216
217         tmp = (char *)evbuffer_pullup(evb, 4 + 9 + 7);
218         tt_assert(!strncmp(tmp, "elsesomething1/hello", 4 + 9 + 7));
219         evbuffer_validate(evb);
220
221         evbuffer_drain(evb, -1);
222         evbuffer_validate(evb);
223         evbuffer_drain(evb_two, -1);
224         evbuffer_validate(evb);
225
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);
232         }
233
234         tt_assert(evbuffer_get_length(evb_two) == 0);
235         tt_assert(evbuffer_get_length(evb) == i * sizeof(buffer));
236
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);
243
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");
249
250         evbuffer_validate(evb);
251
252
253         /* testing one-vector reserve and commit */
254         {
255                 struct evbuffer_iovec v[1];
256                 char *buf;
257                 int i, j, r;
258
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);
264
265                         evbuffer_validate(evb);
266                         buf = v[0].iov_base;
267                         for (j = 0; j < 10000; ++j) {
268                                 buf[j] = j;
269                         }
270                         evbuffer_validate(evb);
271
272                         tt_int_op(evbuffer_commit_space(evb, v, 1), ==, 0);
273                         evbuffer_validate(evb);
274
275                         tt_assert(evbuffer_get_length(evb) >= 10000);
276
277                         evbuffer_drain(evb, j * 5000);
278                         evbuffer_validate(evb);
279                 }
280         }
281
282  end:
283         evbuffer_free(evb);
284         evbuffer_free(evb_two);
285 }
286
287 static void
288 test_evbuffer_reserve2(void *ptr)
289 {
290         /* Test the two-vector cases of reserve/commit. */
291         struct evbuffer *buf = evbuffer_new();
292         int n, i;
293         struct evbuffer_iovec v[2];
294         size_t remaining;
295         char *cp, *cp2;
296
297         /* First chunk will necessarily be one chunk. Use 512 bytes of it.*/
298         n = evbuffer_reserve_space(buf, 1024, v, 2);
299         tt_int_op(n, ==, 1);
300         tt_int_op(evbuffer_get_length(buf), ==, 0);
301         tt_assert(v[0].iov_base != NULL);
302         tt_int_op(v[0].iov_len, >=, 1024);
303         memset(v[0].iov_base, 'X', 512);
304         cp = v[0].iov_base;
305         remaining = v[0].iov_len - 512;
306         v[0].iov_len = 512;
307         evbuffer_validate(buf);
308         tt_int_op(0, ==, evbuffer_commit_space(buf, v, 1));
309         tt_int_op(evbuffer_get_length(buf), ==, 512);
310         evbuffer_validate(buf);
311
312         /* Ask for another same-chunk request, in an existing chunk. Use 8
313          * bytes of it. */
314         n = evbuffer_reserve_space(buf, 32, v, 2);
315         tt_int_op(n, ==, 1);
316         tt_assert(cp + 512 == v[0].iov_base);
317         tt_int_op(remaining, ==, v[0].iov_len);
318         memset(v[0].iov_base, 'Y', 8);
319         v[0].iov_len = 8;
320         tt_int_op(0, ==, evbuffer_commit_space(buf, v, 1));
321         tt_int_op(evbuffer_get_length(buf), ==, 520);
322         remaining -= 8;
323         evbuffer_validate(buf);
324
325         /* Now ask for a request that will be split. Use only one byte of it,
326            though. */
327         n = evbuffer_reserve_space(buf, remaining+64, v, 2);
328         tt_int_op(n, ==, 2);
329         tt_assert(cp + 520 == v[0].iov_base);
330         tt_int_op(remaining, ==, v[0].iov_len);
331         tt_assert(v[1].iov_base);
332         tt_assert(v[1].iov_len >= 64);
333         cp2 = v[1].iov_base;
334         memset(v[0].iov_base, 'Z', 1);
335         v[0].iov_len = 1;
336         tt_int_op(0, ==, evbuffer_commit_space(buf, v, 1));
337         tt_int_op(evbuffer_get_length(buf), ==, 521);
338         remaining -= 1;
339         evbuffer_validate(buf);
340
341         /* Now ask for a request that will be split. Use some of the first
342          * part and some of the second. */
343         n = evbuffer_reserve_space(buf, remaining+64, v, 2);
344         evbuffer_validate(buf);
345         tt_int_op(n, ==, 2);
346         tt_assert(cp + 521 == v[0].iov_base);
347         tt_int_op(remaining, ==, v[0].iov_len);
348         tt_assert(v[1].iov_base == cp2);
349         tt_assert(v[1].iov_len >= 64);
350         memset(v[0].iov_base, 'W', 400);
351         v[0].iov_len = 400;
352         memset(v[1].iov_base, 'x', 60);
353         v[1].iov_len = 60;
354         tt_int_op(0, ==, evbuffer_commit_space(buf, v, 2));
355         tt_int_op(evbuffer_get_length(buf), ==, 981);
356         evbuffer_validate(buf);
357
358         /* Now peek to make sure stuff got made how we like. */
359         memset(v,0,sizeof(v));
360         n = evbuffer_peek(buf, -1, NULL, v, 2);
361         tt_int_op(n, ==, 2);
362         tt_int_op(v[0].iov_len, ==, 921);
363         tt_int_op(v[1].iov_len, ==, 60);
364
365         cp = v[0].iov_base;
366         for (i=0; i<512; ++i)
367                 tt_int_op(cp[i], ==, 'X');
368         for (i=512; i<520; ++i)
369                 tt_int_op(cp[i], ==, 'Y');
370         for (i=520; i<521; ++i)
371                 tt_int_op(cp[i], ==, 'Z');
372         for (i=521; i<921; ++i)
373                 tt_int_op(cp[i], ==, 'W');
374
375         cp = v[1].iov_base;
376         for (i=0; i<60; ++i)
377                 tt_int_op(cp[i], ==, 'x');
378
379 end:
380         evbuffer_free(buf);
381 }
382
383 static void
384 test_evbuffer_reserve_many(void *ptr)
385 {
386         /* This is a glass-box test to handle expanding a buffer with more
387          * chunks and reallocating chunks as needed */
388         struct evbuffer *buf = evbuffer_new();
389         struct evbuffer_iovec v[8];
390         int n;
391         size_t sz;
392         int add_data = ptr && !strcmp(ptr, "add");
393         int fill_first = ptr && !strcmp(ptr, "fill");
394         char *cp1, *cp2;
395
396         /* When reserving the the first chunk, we just allocate it */
397         n = evbuffer_reserve_space(buf, 128, v, 2);
398         evbuffer_validate(buf);
399         tt_int_op(n, ==, 1);
400         tt_assert(v[0].iov_len >= 128);
401         sz = v[0].iov_len;
402         cp1 = v[0].iov_base;
403         if (add_data) {
404                 *(char*)v[0].iov_base = 'X';
405                 v[0].iov_len = 1;
406                 n = evbuffer_commit_space(buf, v, 1);
407                 tt_int_op(n, ==, 0);
408         } else if (fill_first) {
409                 memset(v[0].iov_base, 'X', v[0].iov_len);
410                 n = evbuffer_commit_space(buf, v, 1);
411                 tt_int_op(n, ==, 0);
412                 n = evbuffer_reserve_space(buf, 128, v, 2);
413                 tt_int_op(n, ==, 1);
414                 sz = v[0].iov_len;
415                 tt_assert(v[0].iov_base != cp1);
416                 cp1 = v[0].iov_base;
417         }
418
419         /* Make another chunk get added. */
420         n = evbuffer_reserve_space(buf, sz+128, v, 2);
421         evbuffer_validate(buf);
422         tt_int_op(n, ==, 2);
423         sz = v[0].iov_len + v[1].iov_len;
424         tt_int_op(sz, >=, v[0].iov_len+128);
425         if (add_data) {
426                 tt_assert(v[0].iov_base == cp1 + 1);
427         } else {
428                 tt_assert(v[0].iov_base == cp1);
429         }
430         cp1 = v[0].iov_base;
431         cp2 = v[1].iov_base;
432
433         /* And a third chunk. */
434         n = evbuffer_reserve_space(buf, sz+128, v, 3);
435         evbuffer_validate(buf);
436         tt_int_op(n, ==, 3);
437         tt_assert(cp1 == v[0].iov_base);
438         tt_assert(cp2 == v[1].iov_base);
439         sz = v[0].iov_len + v[1].iov_len + v[2].iov_len;
440
441         /* Now force a reallocation by asking for more space in only 2
442          * buffers. */
443         n = evbuffer_reserve_space(buf, sz+128, v, 2);
444         evbuffer_validate(buf);
445         if (add_data) {
446                 tt_int_op(n, ==, 2);
447                 tt_assert(cp1 == v[0].iov_base);
448         } else {
449                 tt_int_op(n, ==, 1);
450         }
451
452 end:
453         evbuffer_free(buf);
454 }
455
456 static void
457 test_evbuffer_expand(void *ptr)
458 {
459         char data[4096];
460         struct evbuffer *buf;
461         size_t a,w,u;
462         void *buffer;
463
464         memset(data, 'X', sizeof(data));
465
466         /* Make sure that expand() works on an empty buffer */
467         buf = evbuffer_new();
468         tt_int_op(evbuffer_expand(buf, 20000), ==, 0);
469         evbuffer_validate(buf);
470         a=w=u=0;
471         evbuffer_get_waste(buf, &a,&w,&u);
472         tt_assert(w == 0);
473         tt_assert(u == 0);
474         tt_assert(a >= 20000);
475         tt_assert(buf->first);
476         tt_assert(buf->first == buf->last);
477         tt_assert(buf->first->off == 0);
478         tt_assert(buf->first->buffer_len >= 20000);
479
480         /* Make sure that expand() works as a no-op when there's enough
481          * contiguous space already. */
482         buffer = buf->first->buffer;
483         evbuffer_add(buf, data, 1024);
484         tt_int_op(evbuffer_expand(buf, 1024), ==, 0);
485         tt_assert(buf->first->buffer == buffer);
486         evbuffer_validate(buf);
487         evbuffer_free(buf);
488
489         /* Make sure that expand() can work by moving misaligned data
490          * when it makes sense to do so. */
491         buf = evbuffer_new();
492         evbuffer_add(buf, data, 400);
493         {
494                 int n = (int)(buf->first->buffer_len - buf->first->off - 1);
495                 tt_assert(n < (int)sizeof(data));
496                 evbuffer_add(buf, data, n);
497         }
498         tt_assert(buf->first == buf->last);
499         tt_assert(buf->first->off == buf->first->buffer_len - 1);
500         evbuffer_drain(buf, buf->first->off - 1);
501         tt_assert(1 == evbuffer_get_length(buf));
502         tt_assert(buf->first->misalign > 0);
503         tt_assert(buf->first->off == 1);
504         buffer = buf->first->buffer;
505         tt_assert(evbuffer_expand(buf, 40) == 0);
506         tt_assert(buf->first == buf->last);
507         tt_assert(buf->first->off == 1);
508         tt_assert(buf->first->buffer == buffer);
509         tt_assert(buf->first->misalign == 0);
510         evbuffer_validate(buf);
511         evbuffer_free(buf);
512
513         /* add, expand, pull-up: This used to crash libevent. */
514         buf = evbuffer_new();
515
516         evbuffer_add(buf, data, sizeof(data));
517         evbuffer_add(buf, data, sizeof(data));
518         evbuffer_add(buf, data, sizeof(data));
519
520         evbuffer_validate(buf);
521         evbuffer_expand(buf, 1024);
522         evbuffer_validate(buf);
523         evbuffer_pullup(buf, -1);
524         evbuffer_validate(buf);
525
526 end:
527         evbuffer_free(buf);
528 }
529
530
531 static int reference_cb_called;
532 static void
533 reference_cb(const void *data, size_t len, void *extra)
534 {
535         tt_str_op(data, ==, "this is what we add as read-only memory.");
536         tt_int_op(len, ==, strlen(data));
537         tt_want(extra == (void *)0xdeadaffe);
538         ++reference_cb_called;
539 end:
540         ;
541 }
542
543 static void
544 test_evbuffer_reference(void *ptr)
545 {
546         struct evbuffer *src = evbuffer_new();
547         struct evbuffer *dst = evbuffer_new();
548         struct evbuffer_iovec v[1];
549         const char *data = "this is what we add as read-only memory.";
550         reference_cb_called = 0;
551
552         tt_assert(evbuffer_add_reference(src, data, strlen(data),
553                  reference_cb, (void *)0xdeadaffe) != -1);
554
555         evbuffer_reserve_space(dst, strlen(data), v, 1);
556         tt_assert(evbuffer_remove(src, v[0].iov_base, 10) != -1);
557
558         evbuffer_validate(src);
559         evbuffer_validate(dst);
560
561         /* make sure that we don't write data at the beginning */
562         evbuffer_prepend(src, "aaaaa", 5);
563         evbuffer_validate(src);
564         evbuffer_drain(src, 5);
565
566         tt_assert(evbuffer_remove(src, ((char*)(v[0].iov_base)) + 10,
567                 strlen(data) - 10) != -1);
568
569         v[0].iov_len = strlen(data);
570
571         evbuffer_commit_space(dst, v, 1);
572         evbuffer_validate(src);
573         evbuffer_validate(dst);
574
575         tt_int_op(reference_cb_called, ==, 1);
576
577         tt_assert(!memcmp(evbuffer_pullup(dst, strlen(data)),
578                           data, strlen(data)));
579         evbuffer_validate(dst);
580
581  end:
582         evbuffer_free(dst);
583         evbuffer_free(src);
584 }
585
586 int _evbuffer_testing_use_sendfile(void);
587 int _evbuffer_testing_use_mmap(void);
588 int _evbuffer_testing_use_linear_file_access(void);
589
590 static void
591 test_evbuffer_add_file(void *ptr)
592 {
593         const char *impl = ptr;
594         struct evbuffer *src = evbuffer_new();
595         const char *data = "this is what we add as file system data.";
596         size_t datalen;
597         const char *compare;
598         int fd = -1;
599         evutil_socket_t pair[2] = {-1, -1};
600         int r=0, n_written=0;
601
602         /* Add a test for a big file. XXXX */
603
604         tt_assert(impl);
605         if (!strcmp(impl, "sendfile")) {
606                 if (!_evbuffer_testing_use_sendfile())
607                         tt_skip();
608                 TT_BLATHER(("Using sendfile-based implementaion"));
609         } else if (!strcmp(impl, "mmap")) {
610                 if (!_evbuffer_testing_use_mmap())
611                         tt_skip();
612                 TT_BLATHER(("Using mmap-based implementaion"));
613         } else if (!strcmp(impl, "linear")) {
614                 if (!_evbuffer_testing_use_linear_file_access())
615                         tt_skip();
616                 TT_BLATHER(("Using read-based implementaion"));
617         } else {
618                 TT_DIE(("Didn't recognize the implementation"));
619         }
620
621 #if defined(_EVENT_HAVE_SENDFILE) && defined(__sun__) && defined(__svr4__)
622         /* We need to use a pair of AF_INET sockets, since Solaris
623            doesn't support sendfile() over AF_UNIX. */
624         if (evutil_ersatz_socketpair(AF_INET, SOCK_STREAM, 0, pair) == -1)
625                 tt_abort_msg("ersatz_socketpair failed");
626 #else
627         if (evutil_socketpair(AF_UNIX, SOCK_STREAM, 0, pair) == -1)
628                 tt_abort_msg("socketpair failed");
629 #endif
630
631         datalen = strlen(data);
632         fd = regress_make_tmpfile(data, datalen);
633
634         tt_assert(fd != -1);
635
636         tt_assert(evbuffer_add_file(src, fd, 0, datalen) != -1);
637
638         evbuffer_validate(src);
639
640         while (evbuffer_get_length(src) &&
641             (r = evbuffer_write(src, pair[0])) > 0) {
642                 evbuffer_validate(src);
643                 n_written += r;
644         }
645         tt_int_op(r, !=, -1);
646         tt_int_op(n_written, ==, datalen);
647
648         evbuffer_validate(src);
649         tt_int_op(evbuffer_read(src, pair[1], (int)strlen(data)), ==, datalen);
650         evbuffer_validate(src);
651         compare = (char *)evbuffer_pullup(src, datalen);
652         tt_assert(compare != NULL);
653         if (memcmp(compare, data, datalen))
654                 tt_abort_msg("Data from add_file differs.");
655
656         evbuffer_validate(src);
657  end:
658         if (pair[0] >= 0)
659                 evutil_closesocket(pair[0]);
660         if (pair[1] >= 0)
661                 evutil_closesocket(pair[1]);
662         evbuffer_free(src);
663 }
664
665 #ifndef _EVENT_DISABLE_MM_REPLACEMENT
666 static void *
667 failing_malloc(size_t how_much)
668 {
669         errno = ENOMEM;
670         return NULL;
671 }
672 #endif
673
674 static void
675 test_evbuffer_readln(void *ptr)
676 {
677         struct evbuffer *evb = evbuffer_new();
678         struct evbuffer *evb_tmp = evbuffer_new();
679         const char *s;
680         char *cp = NULL;
681         size_t sz;
682
683 #define tt_line_eq(content)                                             \
684         TT_STMT_BEGIN                                                   \
685         if (!cp || sz != strlen(content) || strcmp(cp, content)) {      \
686                 TT_DIE(("Wanted %s; got %s [%d]", content, cp, (int)sz)); \
687         }                                                               \
688         TT_STMT_END
689
690         /* Test EOL_ANY. */
691         s = "complex silly newline\r\n\n\r\n\n\rmore\0\n";
692         evbuffer_add(evb, s, strlen(s)+2);
693         evbuffer_validate(evb);
694         cp = evbuffer_readln(evb, &sz, EVBUFFER_EOL_ANY);
695         tt_line_eq("complex silly newline");
696         free(cp);
697         evbuffer_validate(evb);
698         cp = evbuffer_readln(evb, &sz, EVBUFFER_EOL_ANY);
699         if (!cp || sz != 5 || memcmp(cp, "more\0\0", 6))
700                 tt_abort_msg("Not as expected");
701         tt_uint_op(evbuffer_get_length(evb), ==, 0);
702         evbuffer_validate(evb);
703         s = "\nno newline";
704         evbuffer_add(evb, s, strlen(s));
705         free(cp);
706         evbuffer_validate(evb);
707         cp = evbuffer_readln(evb, &sz, EVBUFFER_EOL_ANY);
708         tt_line_eq("");
709         free(cp);
710         evbuffer_validate(evb);
711         cp = evbuffer_readln(evb, &sz, EVBUFFER_EOL_ANY);
712         tt_assert(!cp);
713         evbuffer_validate(evb);
714         evbuffer_drain(evb, evbuffer_get_length(evb));
715         tt_assert(evbuffer_get_length(evb) == 0);
716         evbuffer_validate(evb);
717
718         /* Test EOL_CRLF */
719         s = "Line with\rin the middle\nLine with good crlf\r\n\nfinal\n";
720         evbuffer_add(evb, s, strlen(s));
721         evbuffer_validate(evb);
722         cp = evbuffer_readln(evb, &sz, EVBUFFER_EOL_CRLF);
723         tt_line_eq("Line with\rin the middle");
724         free(cp);
725         evbuffer_validate(evb);
726
727         cp = evbuffer_readln(evb, &sz, EVBUFFER_EOL_CRLF);
728         tt_line_eq("Line with good crlf");
729         free(cp);
730         evbuffer_validate(evb);
731
732         cp = evbuffer_readln(evb, &sz, EVBUFFER_EOL_CRLF);
733         tt_line_eq("");
734         free(cp);
735         evbuffer_validate(evb);
736
737         cp = evbuffer_readln(evb, &sz, EVBUFFER_EOL_CRLF);
738         tt_line_eq("final");
739         s = "x";
740         evbuffer_validate(evb);
741         evbuffer_add(evb, s, 1);
742         evbuffer_validate(evb);
743         free(cp);
744         cp = evbuffer_readln(evb, &sz, EVBUFFER_EOL_CRLF);
745         tt_assert(!cp);
746         evbuffer_validate(evb);
747
748         /* Test CRLF_STRICT */
749         s = " and a bad crlf\nand a good one\r\n\r\nMore\r";
750         evbuffer_add(evb, s, strlen(s));
751         evbuffer_validate(evb);
752         cp = evbuffer_readln(evb, &sz, EVBUFFER_EOL_CRLF_STRICT);
753         tt_line_eq("x and a bad crlf\nand a good one");
754         free(cp);
755         evbuffer_validate(evb);
756
757         cp = evbuffer_readln(evb, &sz, EVBUFFER_EOL_CRLF_STRICT);
758         tt_line_eq("");
759         free(cp);
760         evbuffer_validate(evb);
761
762         cp = evbuffer_readln(evb, &sz, EVBUFFER_EOL_CRLF_STRICT);
763         tt_assert(!cp);
764         evbuffer_validate(evb);
765         evbuffer_add(evb, "\n", 1);
766         evbuffer_validate(evb);
767
768         cp = evbuffer_readln(evb, &sz, EVBUFFER_EOL_CRLF_STRICT);
769         tt_line_eq("More");
770         free(cp);
771         tt_assert(evbuffer_get_length(evb) == 0);
772         evbuffer_validate(evb);
773
774         s = "An internal CR\r is not an eol\r\nNor is a lack of one";
775         evbuffer_add(evb, s, strlen(s));
776         cp = evbuffer_readln(evb, &sz, EVBUFFER_EOL_CRLF_STRICT);
777         tt_line_eq("An internal CR\r is not an eol");
778         free(cp);
779         evbuffer_validate(evb);
780
781         cp = evbuffer_readln(evb, &sz, EVBUFFER_EOL_CRLF_STRICT);
782         tt_assert(!cp);
783         evbuffer_validate(evb);
784
785         evbuffer_add(evb, "\r\n", 2);
786         evbuffer_validate(evb);
787         cp = evbuffer_readln(evb, &sz, EVBUFFER_EOL_CRLF_STRICT);
788         tt_line_eq("Nor is a lack of one");
789         free(cp);
790         tt_assert(evbuffer_get_length(evb) == 0);
791         evbuffer_validate(evb);
792
793         /* Test LF */
794         s = "An\rand a nl\n\nText";
795         evbuffer_add(evb, s, strlen(s));
796         evbuffer_validate(evb);
797
798         cp = evbuffer_readln(evb, &sz, EVBUFFER_EOL_LF);
799         tt_line_eq("An\rand a nl");
800         free(cp);
801         evbuffer_validate(evb);
802
803         cp = evbuffer_readln(evb, &sz, EVBUFFER_EOL_LF);
804         tt_line_eq("");
805         free(cp);
806         evbuffer_validate(evb);
807
808         cp = evbuffer_readln(evb, &sz, EVBUFFER_EOL_LF);
809         tt_assert(!cp);
810         free(cp);
811         evbuffer_add(evb, "\n", 1);
812         evbuffer_validate(evb);
813         cp = evbuffer_readln(evb, &sz, EVBUFFER_EOL_LF);
814         tt_line_eq("Text");
815         free(cp);
816         evbuffer_validate(evb);
817
818         /* Test CRLF_STRICT - across boundaries*/
819         s = " and a bad crlf\nand a good one\r";
820         evbuffer_add(evb_tmp, s, strlen(s));
821         evbuffer_validate(evb);
822         evbuffer_add_buffer(evb, evb_tmp);
823         evbuffer_validate(evb);
824         s = "\n\r";
825         evbuffer_add(evb_tmp, s, strlen(s));
826         evbuffer_validate(evb);
827         evbuffer_add_buffer(evb, evb_tmp);
828         evbuffer_validate(evb);
829         s = "\nMore\r";
830         evbuffer_add(evb_tmp, s, strlen(s));
831         evbuffer_validate(evb);
832         evbuffer_add_buffer(evb, evb_tmp);
833         evbuffer_validate(evb);
834
835         cp = evbuffer_readln(evb, &sz, EVBUFFER_EOL_CRLF_STRICT);
836         tt_line_eq(" and a bad crlf\nand a good one");
837         free(cp);
838         evbuffer_validate(evb);
839
840         cp = evbuffer_readln(evb, &sz, EVBUFFER_EOL_CRLF_STRICT);
841         tt_line_eq("");
842         free(cp);
843         evbuffer_validate(evb);
844
845         cp = evbuffer_readln(evb, &sz, EVBUFFER_EOL_CRLF_STRICT);
846         tt_assert(!cp);
847         free(cp);
848         evbuffer_validate(evb);
849         evbuffer_add(evb, "\n", 1);
850         evbuffer_validate(evb);
851         cp = evbuffer_readln(evb, &sz, EVBUFFER_EOL_CRLF_STRICT);
852         tt_line_eq("More");
853         free(cp); cp = NULL;
854         evbuffer_validate(evb);
855         tt_assert(evbuffer_get_length(evb) == 0);
856
857         /* Test memory problem*/
858         s = "one line\ntwo line\nblue line";
859         evbuffer_add(evb_tmp, s, strlen(s));
860         evbuffer_validate(evb);
861         evbuffer_add_buffer(evb, evb_tmp);
862         evbuffer_validate(evb);
863
864         cp = evbuffer_readln(evb, &sz, EVBUFFER_EOL_LF);
865         tt_line_eq("one line");
866         free(cp); cp = NULL;
867         evbuffer_validate(evb);
868
869         /* the next call to readline should fail */
870 #ifndef _EVENT_DISABLE_MM_REPLACEMENT
871         event_set_mem_functions(failing_malloc, realloc, free);
872         cp = evbuffer_readln(evb, &sz, EVBUFFER_EOL_LF);
873         tt_assert(cp == NULL);
874         evbuffer_validate(evb);
875
876         /* now we should get the next line back */
877         event_set_mem_functions(malloc, realloc, free);
878 #endif
879         cp = evbuffer_readln(evb, &sz, EVBUFFER_EOL_LF);
880         tt_line_eq("two line");
881         free(cp); cp = NULL;
882         evbuffer_validate(evb);
883
884         test_ok = 1;
885  end:
886         evbuffer_free(evb);
887         evbuffer_free(evb_tmp);
888         if (cp) free(cp);
889 }
890
891 static void
892 test_evbuffer_iterative(void *ptr)
893 {
894         struct evbuffer *buf = evbuffer_new();
895         const char *abc = "abcdefghijklmnopqrstvuwxyzabcdefghijklmnopqrstvuwxyzabcdefghijklmnopqrstvuwxyzabcdefghijklmnopqrstvuwxyz";
896         unsigned i, j, sum, n;
897
898         sum = 0;
899         n = 0;
900         for (i = 0; i < 1000; ++i) {
901                 for (j = 1; j < strlen(abc); ++j) {
902                         char format[32];
903                         evutil_snprintf(format, sizeof(format), "%%%u.%us", j, j);
904                         evbuffer_add_printf(buf, format, abc);
905
906                         /* Only check for rep violations every so often.
907                            Walking over the whole list of chains can get
908                            pretty expensive as it gets long.
909                          */
910                         if ((n % 337) == 0)
911                                 evbuffer_validate(buf);
912
913                         sum += j;
914                         n++;
915                 }
916         }
917         evbuffer_validate(buf);
918
919         tt_uint_op(sum, ==, evbuffer_get_length(buf));
920
921         {
922                 size_t a,w,u;
923                 a=w=u=0;
924                 evbuffer_get_waste(buf, &a, &w, &u);
925                 if (0)
926                         printf("Allocated: %u.\nWasted: %u.\nUsed: %u.",
927                             (unsigned)a, (unsigned)w, (unsigned)u);
928                 tt_assert( ((double)w)/a < .125);
929         }
930  end:
931         evbuffer_free(buf);
932
933 }
934
935 static void
936 test_evbuffer_find(void *ptr)
937 {
938         u_char* p;
939         const char* test1 = "1234567890\r\n";
940         const char* test2 = "1234567890\r";
941 #define EVBUFFER_INITIAL_LENGTH 256
942         char test3[EVBUFFER_INITIAL_LENGTH];
943         unsigned int i;
944         struct evbuffer * buf = evbuffer_new();
945
946         /* make sure evbuffer_find doesn't match past the end of the buffer */
947         evbuffer_add(buf, (u_char*)test1, strlen(test1));
948         evbuffer_validate(buf);
949         evbuffer_drain(buf, strlen(test1));
950         evbuffer_validate(buf);
951         evbuffer_add(buf, (u_char*)test2, strlen(test2));
952         evbuffer_validate(buf);
953         p = evbuffer_find(buf, (u_char*)"\r\n", 2);
954         tt_want(p == NULL);
955
956         /*
957          * drain the buffer and do another find; in r309 this would
958          * read past the allocated buffer causing a valgrind error.
959          */
960         evbuffer_drain(buf, strlen(test2));
961         evbuffer_validate(buf);
962         for (i = 0; i < EVBUFFER_INITIAL_LENGTH; ++i)
963                 test3[i] = 'a';
964         test3[EVBUFFER_INITIAL_LENGTH - 1] = 'x';
965         evbuffer_add(buf, (u_char *)test3, EVBUFFER_INITIAL_LENGTH);
966         evbuffer_validate(buf);
967         p = evbuffer_find(buf, (u_char *)"xy", 2);
968         tt_want(p == NULL);
969
970         /* simple test for match at end of allocated buffer */
971         p = evbuffer_find(buf, (u_char *)"ax", 2);
972         tt_assert(p != NULL);
973         tt_want(strncmp((char*)p, "ax", 2) == 0);
974
975 end:
976         if (buf)
977                 evbuffer_free(buf);
978 }
979
980 static void
981 test_evbuffer_ptr_set(void *ptr)
982 {
983         struct evbuffer *buf = evbuffer_new();
984         struct evbuffer_ptr pos;
985         struct evbuffer_iovec v[1];
986
987         /* create some chains */
988         evbuffer_reserve_space(buf, 5000, v, 1);
989         v[0].iov_len = 5000;
990         memset(v[0].iov_base, 1, v[0].iov_len);
991         evbuffer_commit_space(buf, v, 1);
992         evbuffer_validate(buf);
993
994         evbuffer_reserve_space(buf, 4000, v, 1);
995         v[0].iov_len = 4000;
996         memset(v[0].iov_base, 2, v[0].iov_len);
997         evbuffer_commit_space(buf, v, 1);
998
999         evbuffer_reserve_space(buf, 3000, v, 1);
1000         v[0].iov_len = 3000;
1001         memset(v[0].iov_base, 3, v[0].iov_len);
1002         evbuffer_commit_space(buf, v, 1);
1003         evbuffer_validate(buf);
1004
1005         tt_int_op(evbuffer_get_length(buf), ==, 12000);
1006
1007         tt_assert(evbuffer_ptr_set(buf, &pos, 13000, EVBUFFER_PTR_SET) == -1);
1008         tt_assert(pos.pos == -1);
1009         tt_assert(evbuffer_ptr_set(buf, &pos, 0, EVBUFFER_PTR_SET) == 0);
1010         tt_assert(pos.pos == 0);
1011         tt_assert(evbuffer_ptr_set(buf, &pos, 13000, EVBUFFER_PTR_ADD) == -1);
1012
1013         tt_assert(evbuffer_ptr_set(buf, &pos, 0, EVBUFFER_PTR_SET) == 0);
1014         tt_assert(pos.pos == 0);
1015         tt_assert(evbuffer_ptr_set(buf, &pos, 10000, EVBUFFER_PTR_ADD) == 0);
1016         tt_assert(pos.pos == 10000);
1017         tt_assert(evbuffer_ptr_set(buf, &pos, 1000, EVBUFFER_PTR_ADD) == 0);
1018         tt_assert(pos.pos == 11000);
1019         tt_assert(evbuffer_ptr_set(buf, &pos, 1000, EVBUFFER_PTR_ADD) == -1);
1020         tt_assert(pos.pos == -1);
1021
1022 end:
1023         if (buf)
1024                 evbuffer_free(buf);
1025 }
1026
1027 static void
1028 test_evbuffer_search(void *ptr)
1029 {
1030         struct evbuffer *buf = evbuffer_new();
1031         struct evbuffer *tmp = evbuffer_new();
1032         struct evbuffer_ptr pos, end;
1033
1034         /* set up our chains */
1035         evbuffer_add_printf(tmp, "hello");  /* 5 chars */
1036         evbuffer_add_buffer(buf, tmp);
1037         evbuffer_add_printf(tmp, "foo");    /* 3 chars */
1038         evbuffer_add_buffer(buf, tmp);
1039         evbuffer_add_printf(tmp, "cat");    /* 3 chars */
1040         evbuffer_add_buffer(buf, tmp);
1041         evbuffer_add_printf(tmp, "attack");
1042         evbuffer_add_buffer(buf, tmp);
1043
1044         pos = evbuffer_search(buf, "attack", 6, NULL);
1045         tt_int_op(pos.pos, ==, 11);
1046         pos = evbuffer_search(buf, "attacker", 8, NULL);
1047         tt_int_op(pos.pos, ==, -1);
1048
1049         /* test continuing search */
1050         pos = evbuffer_search(buf, "oc", 2, NULL);
1051         tt_int_op(pos.pos, ==, 7);
1052         pos = evbuffer_search(buf, "cat", 3, &pos);
1053         tt_int_op(pos.pos, ==, 8);
1054         pos = evbuffer_search(buf, "tacking", 7, &pos);
1055         tt_int_op(pos.pos, ==, -1);
1056
1057         evbuffer_ptr_set(buf, &pos, 5, EVBUFFER_PTR_SET);
1058         pos = evbuffer_search(buf, "foo", 3, &pos);
1059         tt_int_op(pos.pos, ==, 5);
1060
1061         evbuffer_ptr_set(buf, &pos, 2, EVBUFFER_PTR_ADD);
1062         pos = evbuffer_search(buf, "tat", 3, &pos);
1063         tt_int_op(pos.pos, ==, 10);
1064
1065         /* test bounded search. */
1066         /* Set "end" to the first t in "attack". */
1067         evbuffer_ptr_set(buf, &end, 12, EVBUFFER_PTR_SET);
1068         pos = evbuffer_search_range(buf, "foo", 3, NULL, &end);
1069         tt_int_op(pos.pos, ==, 5);
1070         pos = evbuffer_search_range(buf, "foocata", 7, NULL, &end);
1071         tt_int_op(pos.pos, ==, 5);
1072         pos = evbuffer_search_range(buf, "foocatat", 8, NULL, &end);
1073         tt_int_op(pos.pos, ==, -1);
1074         pos = evbuffer_search_range(buf, "ack", 3, NULL, &end);
1075         tt_int_op(pos.pos, ==, -1);
1076
1077 end:
1078         if (buf)
1079                 evbuffer_free(buf);
1080         if (tmp)
1081                 evbuffer_free(tmp);
1082 }
1083
1084 static void
1085 log_change_callback(struct evbuffer *buffer,
1086     const struct evbuffer_cb_info *cbinfo,
1087     void *arg)
1088 {
1089
1090         size_t old_len = cbinfo->orig_size;
1091         size_t new_len = old_len + cbinfo->n_added - cbinfo->n_deleted;
1092         struct evbuffer *out = arg;
1093         evbuffer_add_printf(out, "%lu->%lu; ", (unsigned long)old_len,
1094                             (unsigned long)new_len);
1095 }
1096 static void
1097 self_draining_callback(struct evbuffer *evbuffer, size_t old_len,
1098                 size_t new_len, void *arg)
1099 {
1100         if (new_len > old_len)
1101                 evbuffer_drain(evbuffer, new_len);
1102 }
1103
1104 static void
1105 test_evbuffer_callbacks(void *ptr)
1106 {
1107         struct evbuffer *buf = evbuffer_new();
1108         struct evbuffer *buf_out1 = evbuffer_new();
1109         struct evbuffer *buf_out2 = evbuffer_new();
1110         struct evbuffer_cb_entry *cb1, *cb2;
1111
1112         cb1 = evbuffer_add_cb(buf, log_change_callback, buf_out1);
1113         cb2 = evbuffer_add_cb(buf, log_change_callback, buf_out2);
1114
1115         /* Let's run through adding and deleting some stuff from the buffer
1116          * and turning the callbacks on and off and removing them.  The callback
1117          * adds a summary of length changes to buf_out1/buf_out2 when called. */
1118         /* size: 0-> 36. */
1119         evbuffer_add_printf(buf, "The %d magic words are spotty pudding", 2);
1120         evbuffer_validate(buf);
1121         evbuffer_cb_clear_flags(buf, cb2, EVBUFFER_CB_ENABLED);
1122         evbuffer_drain(buf, 10); /*36->26*/
1123         evbuffer_validate(buf);
1124         evbuffer_prepend(buf, "Hello", 5);/*26->31*/
1125         evbuffer_cb_set_flags(buf, cb2, EVBUFFER_CB_ENABLED);
1126         evbuffer_add_reference(buf, "Goodbye", 7, NULL, NULL); /*31->38*/
1127         evbuffer_remove_cb_entry(buf, cb1);
1128         evbuffer_validate(buf);
1129         evbuffer_drain(buf, evbuffer_get_length(buf)); /*38->0*/;
1130         tt_assert(-1 == evbuffer_remove_cb(buf, log_change_callback, NULL));
1131         evbuffer_add(buf, "X", 1); /* 0->1 */
1132         tt_assert(!evbuffer_remove_cb(buf, log_change_callback, buf_out2));
1133         evbuffer_validate(buf);
1134
1135         tt_str_op(evbuffer_pullup(buf_out1, -1), ==,
1136                   "0->36; 36->26; 26->31; 31->38; ");
1137         tt_str_op(evbuffer_pullup(buf_out2, -1), ==,
1138                   "0->36; 31->38; 38->0; 0->1; ");
1139         evbuffer_drain(buf_out1, evbuffer_get_length(buf_out1));
1140         evbuffer_drain(buf_out2, evbuffer_get_length(buf_out2));
1141         /* Let's test the obsolete buffer_setcb function too. */
1142         cb1 = evbuffer_add_cb(buf, log_change_callback, buf_out1);
1143         cb2 = evbuffer_add_cb(buf, log_change_callback, buf_out2);
1144         evbuffer_setcb(buf, self_draining_callback, NULL);
1145         evbuffer_add_printf(buf, "This should get drained right away.");
1146         tt_uint_op(evbuffer_get_length(buf), ==, 0);
1147         tt_uint_op(evbuffer_get_length(buf_out1), ==, 0);
1148         tt_uint_op(evbuffer_get_length(buf_out2), ==, 0);
1149         evbuffer_setcb(buf, NULL, NULL);
1150         evbuffer_add_printf(buf, "This will not.");
1151         tt_str_op(evbuffer_pullup(buf, -1), ==, "This will not.");
1152         evbuffer_validate(buf);
1153         evbuffer_drain(buf, evbuffer_get_length(buf));
1154         evbuffer_validate(buf);
1155 #if 0
1156         /* Now let's try a suspended callback. */
1157         cb1 = evbuffer_add_cb(buf, log_change_callback, buf_out1);
1158         cb2 = evbuffer_add_cb(buf, log_change_callback, buf_out2);
1159         evbuffer_cb_suspend(buf,cb2);
1160         evbuffer_prepend(buf,"Hello world",11); /*0->11*/
1161         evbuffer_validate(buf);
1162         evbuffer_cb_suspend(buf,cb1);
1163         evbuffer_add(buf,"more",4); /* 11->15 */
1164         evbuffer_cb_unsuspend(buf,cb2);
1165         evbuffer_drain(buf, 4); /* 15->11 */
1166         evbuffer_cb_unsuspend(buf,cb1);
1167         evbuffer_drain(buf, evbuffer_get_length(buf)); /* 11->0 */
1168
1169         tt_str_op(evbuffer_pullup(buf_out1, -1), ==,
1170                   "0->11; 11->11; 11->0; ");
1171         tt_str_op(evbuffer_pullup(buf_out2, -1), ==,
1172                   "0->15; 15->11; 11->0; ");
1173 #endif
1174
1175  end:
1176         if (buf)
1177                 evbuffer_free(buf);
1178         if (buf_out1)
1179                 evbuffer_free(buf_out1);
1180         if (buf_out2)
1181                 evbuffer_free(buf_out2);
1182 }
1183
1184 static int ref_done_cb_called_count = 0;
1185 static void *ref_done_cb_called_with = NULL;
1186 static const void *ref_done_cb_called_with_data = NULL;
1187 static size_t ref_done_cb_called_with_len = 0;
1188 static void ref_done_cb(const void *data, size_t len, void *info)
1189 {
1190         ++ref_done_cb_called_count;
1191         ref_done_cb_called_with = info;
1192         ref_done_cb_called_with_data = data;
1193         ref_done_cb_called_with_len = len;
1194 }
1195
1196 static void
1197 test_evbuffer_add_reference(void *ptr)
1198 {
1199         const char chunk1[] = "If you have found the answer to such a problem";
1200         const char chunk2[] = "you ought to write it up for publication";
1201                           /* -- Knuth's "Notes on the Exercises" from TAOCP */
1202         char tmp[16];
1203         size_t len1 = strlen(chunk1), len2=strlen(chunk2);
1204
1205         struct evbuffer *buf1 = NULL, *buf2 = NULL;
1206
1207         buf1 = evbuffer_new();
1208         tt_assert(buf1);
1209
1210         evbuffer_add_reference(buf1, chunk1, len1, ref_done_cb, (void*)111);
1211         evbuffer_add(buf1, ", ", 2);
1212         evbuffer_add_reference(buf1, chunk2, len2, ref_done_cb, (void*)222);
1213         tt_int_op(evbuffer_get_length(buf1), ==, len1+len2+2);
1214
1215         /* Make sure we can drain a little from a reference. */
1216         tt_int_op(evbuffer_remove(buf1, tmp, 6), ==, 6);
1217         tt_int_op(memcmp(tmp, "If you", 6), ==, 0);
1218         tt_int_op(evbuffer_remove(buf1, tmp, 5), ==, 5);
1219         tt_int_op(memcmp(tmp, " have", 5), ==, 0);
1220
1221         /* Make sure that prepending does not meddle with immutable data */
1222         tt_int_op(evbuffer_prepend(buf1, "I have ", 7), ==, 0);
1223         tt_int_op(memcmp(chunk1, "If you", 6), ==, 0);
1224         evbuffer_validate(buf1);
1225
1226         /* Make sure that when the chunk is over, the callback is invoked. */
1227         evbuffer_drain(buf1, 7); /* Remove prepended stuff. */
1228         evbuffer_drain(buf1, len1-11-1); /* remove all but one byte of chunk1 */
1229         tt_int_op(ref_done_cb_called_count, ==, 0);
1230         evbuffer_remove(buf1, tmp, 1);
1231         tt_int_op(tmp[0], ==, 'm');
1232         tt_assert(ref_done_cb_called_with == (void*)111);
1233         tt_assert(ref_done_cb_called_with_data == chunk1);
1234         tt_assert(ref_done_cb_called_with_len == len1);
1235         tt_int_op(ref_done_cb_called_count, ==, 1);
1236         evbuffer_validate(buf1);
1237
1238         /* Drain some of the remaining chunk, then add it to another buffer */
1239         evbuffer_drain(buf1, 6); /* Remove the ", you ". */
1240         buf2 = evbuffer_new();
1241         tt_assert(buf2);
1242         tt_int_op(ref_done_cb_called_count, ==, 1);
1243         evbuffer_add(buf2, "I ", 2);
1244
1245         evbuffer_add_buffer(buf2, buf1);
1246         tt_int_op(ref_done_cb_called_count, ==, 1);
1247         evbuffer_remove(buf2, tmp, 16);
1248         tt_int_op(memcmp("I ought to write", tmp, 16), ==, 0);
1249         evbuffer_drain(buf2, evbuffer_get_length(buf2));
1250         tt_int_op(ref_done_cb_called_count, ==, 2);
1251         tt_assert(ref_done_cb_called_with == (void*)222);
1252         evbuffer_validate(buf2);
1253
1254         /* Now add more stuff to buf1 and make sure that it gets removed on
1255          * free. */
1256         evbuffer_add(buf1, "You shake and shake the ", 24);
1257         evbuffer_add_reference(buf1, "ketchup bottle", 14, ref_done_cb,
1258             (void*)3333);
1259         evbuffer_add(buf1, ". Nothing comes and then a lot'll.", 42);
1260         evbuffer_free(buf1);
1261         buf1 = NULL;
1262         tt_int_op(ref_done_cb_called_count, ==, 3);
1263         tt_assert(ref_done_cb_called_with == (void*)3333);
1264
1265 end:
1266         if (buf1)
1267                 evbuffer_free(buf1);
1268         if (buf2)
1269                 evbuffer_free(buf2);
1270 }
1271
1272 /* Some cases that we didn't get in test_evbuffer() above, for more coverage. */
1273 static void
1274 test_evbuffer_prepend(void *ptr)
1275 {
1276         struct evbuffer *buf1 = NULL, *buf2 = NULL;
1277         char tmp[128];
1278         int n;
1279
1280         buf1 = evbuffer_new();
1281         tt_assert(buf1);
1282
1283         /* Case 0: The evbuffer is entirely empty. */
1284         evbuffer_prepend(buf1, "This string has 29 characters", 29);
1285         evbuffer_validate(buf1);
1286
1287         /* Case 1: Prepend goes entirely in new chunk. */
1288         evbuffer_prepend(buf1, "Short.", 6);
1289         evbuffer_validate(buf1);
1290
1291         /* Case 2: prepend goes entirely in first chunk. */
1292         evbuffer_drain(buf1, 6+11);
1293         evbuffer_prepend(buf1, "it", 2);
1294         evbuffer_validate(buf1);
1295         tt_assert(!memcmp(buf1->first->buffer+buf1->first->misalign,
1296                 "it has", 6));
1297
1298         /* Case 3: prepend is split over multiple chunks. */
1299         evbuffer_prepend(buf1, "It is no longer true to say ", 28);
1300         evbuffer_validate(buf1);
1301         n = evbuffer_remove(buf1, tmp, sizeof(tmp)-1);
1302         tmp[n]='\0';
1303         tt_str_op(tmp,==,"It is no longer true to say it has 29 characters");
1304
1305         buf2 = evbuffer_new();
1306         tt_assert(buf2);
1307
1308         /* Case 4: prepend a buffer to an empty buffer. */
1309         n = 999;
1310         evbuffer_add_printf(buf1, "Here is string %d. ", n++);
1311         evbuffer_prepend_buffer(buf2, buf1);
1312         evbuffer_validate(buf2);
1313
1314         /* Case 5: prepend a buffer to a nonempty buffer. */
1315         evbuffer_add_printf(buf1, "Here is string %d. ", n++);
1316         evbuffer_prepend_buffer(buf2, buf1);
1317         evbuffer_validate(buf2);
1318         evbuffer_validate(buf1);
1319         n = evbuffer_remove(buf2, tmp, sizeof(tmp)-1);
1320         tmp[n]='\0';
1321         tt_str_op(tmp,==,"Here is string 1000. Here is string 999. ");
1322
1323 end:
1324         if (buf1)
1325                 evbuffer_free(buf1);
1326         if (buf2)
1327                 evbuffer_free(buf2);
1328
1329 }
1330
1331 static void
1332 test_evbuffer_peek(void *info)
1333 {
1334         struct evbuffer *buf = NULL, *tmp_buf = NULL;
1335         int i;
1336         struct evbuffer_iovec v[20];
1337         struct evbuffer_ptr ptr;
1338
1339 #define tt_iov_eq(v, s)                                         \
1340         tt_int_op((v)->iov_len, ==, strlen(s));                 \
1341         tt_assert(!memcmp((v)->iov_base, (s), strlen(s)))
1342
1343         /* Let's make a very fragmented buffer. */
1344         buf = evbuffer_new();
1345         tmp_buf = evbuffer_new();
1346         for (i = 0; i < 16; ++i) {
1347                 evbuffer_add_printf(tmp_buf, "Contents of chunk [%d]\n", i);
1348                 evbuffer_add_buffer(buf, tmp_buf);
1349         }
1350
1351         /* Simple peek: get everything. */
1352         i = evbuffer_peek(buf, -1, NULL, v, 20);
1353         tt_int_op(i, ==, 16); /* we used only 16 chunks. */
1354         tt_iov_eq(&v[0], "Contents of chunk [0]\n");
1355         tt_iov_eq(&v[3], "Contents of chunk [3]\n");
1356         tt_iov_eq(&v[12], "Contents of chunk [12]\n");
1357         tt_iov_eq(&v[15], "Contents of chunk [15]\n");
1358
1359         /* Just get one chunk worth. */
1360         memset(v, 0, sizeof(v));
1361         i = evbuffer_peek(buf, -1, NULL, v, 1);
1362         tt_int_op(i, ==, 1);
1363         tt_iov_eq(&v[0], "Contents of chunk [0]\n");
1364         tt_assert(v[1].iov_base == NULL);
1365
1366         /* Suppose we want at least the first 40 bytes. */
1367         memset(v, 0, sizeof(v));
1368         i = evbuffer_peek(buf, 40, NULL, v, 16);
1369         tt_int_op(i, ==, 2);
1370         tt_iov_eq(&v[0], "Contents of chunk [0]\n");
1371         tt_iov_eq(&v[1], "Contents of chunk [1]\n");
1372         tt_assert(v[2].iov_base == NULL);
1373
1374         /* How many chunks do we need for 100 bytes? */
1375         memset(v, 0, sizeof(v));
1376         i = evbuffer_peek(buf, 100, NULL, NULL, 0);
1377         tt_int_op(i, ==, 5);
1378         tt_assert(v[0].iov_base == NULL);
1379
1380         /* Now we ask for more bytes than we provide chunks for */
1381         memset(v, 0, sizeof(v));
1382         i = evbuffer_peek(buf, 60, NULL, v, 1);
1383         tt_int_op(i, ==, 3);
1384         tt_iov_eq(&v[0], "Contents of chunk [0]\n");
1385         tt_assert(v[1].iov_base == NULL);
1386
1387         /* Now we ask for more bytes than the buffer has. */
1388         memset(v, 0, sizeof(v));
1389         i = evbuffer_peek(buf, 65536, NULL, v, 20);
1390         tt_int_op(i, ==, 16); /* we used only 16 chunks. */
1391         tt_iov_eq(&v[0], "Contents of chunk [0]\n");
1392         tt_iov_eq(&v[3], "Contents of chunk [3]\n");
1393         tt_iov_eq(&v[12], "Contents of chunk [12]\n");
1394         tt_iov_eq(&v[15], "Contents of chunk [15]\n");
1395         tt_assert(v[16].iov_base == NULL);
1396
1397         /* What happens if we try an empty buffer? */
1398         memset(v, 0, sizeof(v));
1399         i = evbuffer_peek(tmp_buf, -1, NULL, v, 20);
1400         tt_int_op(i, ==, 0);
1401         tt_assert(v[0].iov_base == NULL);
1402         memset(v, 0, sizeof(v));
1403         i = evbuffer_peek(tmp_buf, 50, NULL, v, 20);
1404         tt_int_op(i, ==, 0);
1405         tt_assert(v[0].iov_base == NULL);
1406
1407         /* Okay, now time to have fun with pointers. */
1408         memset(v, 0, sizeof(v));
1409         evbuffer_ptr_set(buf, &ptr, 30, EVBUFFER_PTR_SET);
1410         i = evbuffer_peek(buf, 50, &ptr, v, 20);
1411         tt_int_op(i, ==, 3);
1412         tt_iov_eq(&v[0], " of chunk [1]\n");
1413         tt_iov_eq(&v[1], "Contents of chunk [2]\n");
1414         tt_iov_eq(&v[2], "Contents of chunk [3]\n"); /*more than we asked for*/
1415
1416         /* advance to the start of another chain. */
1417         memset(v, 0, sizeof(v));
1418         evbuffer_ptr_set(buf, &ptr, 14, EVBUFFER_PTR_ADD);
1419         i = evbuffer_peek(buf, 44, &ptr, v, 20);
1420         tt_int_op(i, ==, 2);
1421         tt_iov_eq(&v[0], "Contents of chunk [2]\n");
1422         tt_iov_eq(&v[1], "Contents of chunk [3]\n"); /*more than we asked for*/
1423
1424 end:
1425         if (buf)
1426                 evbuffer_free(buf);
1427         if (tmp_buf)
1428                 evbuffer_free(tmp_buf);
1429 }
1430
1431 /* Check whether evbuffer freezing works right.  This is called twice,
1432    once with the argument "start" and once with the argument "end".
1433    When we test "start", we freeze the start of an evbuffer and make sure
1434    that modifying the start of the buffer doesn't work.  When we test
1435    "end", we freeze the end of an evbuffer and make sure that modifying
1436    the end of the buffer doesn't work.
1437  */
1438 static void
1439 test_evbuffer_freeze(void *ptr)
1440 {
1441         struct evbuffer *buf = NULL, *tmp_buf=NULL;
1442         const char string[] = /* Year's End, Richard Wilbur */
1443             "I've known the wind by water banks to shake\n"
1444             "The late leaves down, which frozen where they fell\n"
1445             "And held in ice as dancers in a spell\n"
1446             "Fluttered all winter long into a lake...";
1447         const int start = !strcmp(ptr, "start");
1448         char *cp;
1449         char charbuf[128];
1450         int r;
1451         size_t orig_length;
1452         struct evbuffer_iovec v[1];
1453
1454         if (!start)
1455                 tt_str_op(ptr, ==, "end");
1456
1457         buf = evbuffer_new();
1458         tmp_buf = evbuffer_new();
1459         tt_assert(tmp_buf);
1460
1461         evbuffer_add(buf, string, strlen(string));
1462         evbuffer_freeze(buf, start); /* Freeze the start or the end.*/
1463
1464 #define FREEZE_EQ(a, startcase, endcase)                \
1465         do {                                            \
1466             if (start) {                                \
1467                     tt_int_op((a), ==, (startcase));    \
1468             } else {                                    \
1469                     tt_int_op((a), ==, (endcase));      \
1470             }                                           \
1471         } while (0)
1472
1473
1474         orig_length = evbuffer_get_length(buf);
1475
1476         /* These functions all manipulate the end of buf. */
1477         r = evbuffer_add(buf, "abc", 0);
1478         FREEZE_EQ(r, 0, -1);
1479         r = evbuffer_reserve_space(buf, 10, v, 1);
1480         FREEZE_EQ(r, 1, -1);
1481         if (r == 0) {
1482                 memset(v[0].iov_base, 'X', 10);
1483                 v[0].iov_len = 10;
1484         }
1485         r = evbuffer_commit_space(buf, v, 1);
1486         FREEZE_EQ(r, 0, -1);
1487         r = evbuffer_add_reference(buf, string, 5, NULL, NULL);
1488         FREEZE_EQ(r, 0, -1);
1489         r = evbuffer_add_printf(buf, "Hello %s", "world");
1490         FREEZE_EQ(r, 11, -1);
1491         /* TODO: test add_buffer, add_file, read */
1492
1493         if (!start)
1494                 tt_int_op(orig_length, ==, evbuffer_get_length(buf));
1495
1496         orig_length = evbuffer_get_length(buf);
1497
1498         /* These functions all manipulate the start of buf. */
1499         r = evbuffer_remove(buf, charbuf, 1);
1500         FREEZE_EQ(r, -1, 1);
1501         r = evbuffer_drain(buf, 3);
1502         FREEZE_EQ(r, -1, 0);
1503         r = evbuffer_prepend(buf, "dummy", 5);
1504         FREEZE_EQ(r, -1, 0);
1505         cp = evbuffer_readln(buf, NULL, EVBUFFER_EOL_LF);
1506         FREEZE_EQ(cp==NULL, 1, 0);
1507         if (cp)
1508                 free(cp);
1509         /* TODO: Test remove_buffer, add_buffer, write, prepend_buffer */
1510
1511         if (start)
1512                 tt_int_op(orig_length, ==, evbuffer_get_length(buf));
1513
1514 end:
1515         if (buf)
1516                 evbuffer_free(buf);
1517
1518         if (tmp_buf)
1519                 evbuffer_free(tmp_buf);
1520 }
1521
1522 static void *
1523 setup_passthrough(const struct testcase_t *testcase)
1524 {
1525         return testcase->setup_data;
1526 }
1527 static int
1528 cleanup_passthrough(const struct testcase_t *testcase, void *ptr)
1529 {
1530         (void) ptr;
1531         return 1;
1532 }
1533
1534 static const struct testcase_setup_t nil_setup = {
1535         setup_passthrough,
1536         cleanup_passthrough
1537 };
1538
1539 struct testcase_t evbuffer_testcases[] = {
1540         { "evbuffer", test_evbuffer, 0, NULL, NULL },
1541         { "reserve2", test_evbuffer_reserve2, 0, NULL, NULL },
1542         { "reserve_many", test_evbuffer_reserve_many, 0, NULL, NULL },
1543         { "reserve_many2", test_evbuffer_reserve_many, 0, &nil_setup, (void*)"add" },
1544         { "reserve_many3", test_evbuffer_reserve_many, 0, &nil_setup, (void*)"fill" },
1545         { "expand", test_evbuffer_expand, 0, NULL, NULL },
1546         { "reference", test_evbuffer_reference, 0, NULL, NULL },
1547         { "iterative", test_evbuffer_iterative, 0, NULL, NULL },
1548         { "readln", test_evbuffer_readln, TT_NO_LOGS, &basic_setup, NULL },
1549         { "find", test_evbuffer_find, 0, NULL, NULL },
1550         { "ptr_set", test_evbuffer_ptr_set, 0, NULL, NULL },
1551         { "search", test_evbuffer_search, 0, NULL, NULL },
1552         { "callbacks", test_evbuffer_callbacks, 0, NULL, NULL },
1553         { "add_reference", test_evbuffer_add_reference, 0, NULL, NULL },
1554         { "prepend", test_evbuffer_prepend, TT_FORK, NULL, NULL },
1555         { "peek", test_evbuffer_peek, 0, NULL, NULL },
1556         { "freeze_start", test_evbuffer_freeze, 0, &nil_setup, (void*)"start" },
1557         { "freeze_end", test_evbuffer_freeze, 0, &nil_setup, (void*)"end" },
1558         /* TODO: need a temp file implementation for Windows */
1559         { "add_file_sendfile", test_evbuffer_add_file, TT_FORK, &nil_setup,
1560           (void*)"sendfile" },
1561         { "add_file_mmap", test_evbuffer_add_file, TT_FORK, &nil_setup,
1562           (void*)"mmap" },
1563         { "add_file_linear", test_evbuffer_add_file, TT_FORK, &nil_setup,
1564           (void*)"linear" },
1565
1566         END_OF_TESTCASES
1567 };