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