1 /* $NetBSD: regress_buffer.c,v 1.7 2024/08/18 20:47:23 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 #define ARRAY_SIZE(a) (sizeof(a) / sizeof(a[0])) 69 70 /* Validates that an evbuffer is good. Returns false if it isn't, true if it 71 * is*/ 72 static int 73 evbuffer_validate_(struct evbuffer *buf) 74 { 75 struct evbuffer_chain *chain; 76 size_t sum = 0; 77 int found_last_with_datap = 0; 78 79 if (buf->first == NULL) { 80 tt_assert(buf->last == NULL); 81 tt_assert(buf->total_len == 0); 82 } 83 84 chain = buf->first; 85 86 tt_assert(buf->last_with_datap); 87 if (buf->last_with_datap == &buf->first) 88 found_last_with_datap = 1; 89 90 while (chain != NULL) { 91 if (&chain->next == buf->last_with_datap) 92 found_last_with_datap = 1; 93 sum += chain->off; 94 if (chain->next == NULL) { 95 tt_assert(buf->last == chain); 96 } 97 tt_assert(chain->buffer_len >= chain->misalign + chain->off); 98 chain = chain->next; 99 } 100 101 if (buf->first) 102 tt_assert(*buf->last_with_datap); 103 104 if (*buf->last_with_datap) { 105 chain = *buf->last_with_datap; 106 if (chain->off == 0 || buf->total_len == 0) { 107 tt_assert(chain->off == 0) 108 tt_assert(chain == buf->first); 109 tt_assert(buf->total_len == 0); 110 } 111 chain = chain->next; 112 while (chain != NULL) { 113 tt_assert(chain->off == 0); 114 chain = chain->next; 115 } 116 } else { 117 tt_assert(buf->last_with_datap == &buf->first); 118 } 119 tt_assert(found_last_with_datap); 120 121 tt_assert(sum == buf->total_len); 122 return 1; 123 end: 124 return 0; 125 } 126 127 static void 128 evbuffer_get_waste(struct evbuffer *buf, size_t *allocatedp, size_t *wastedp, size_t *usedp) 129 { 130 struct evbuffer_chain *chain; 131 size_t a, w, u; 132 int n = 0; 133 u = a = w = 0; 134 135 chain = buf->first; 136 /* skip empty at start */ 137 while (chain && chain->off==0) { 138 ++n; 139 a += chain->buffer_len; 140 chain = chain->next; 141 } 142 /* first nonempty chain: stuff at the end only is wasted. */ 143 if (chain) { 144 ++n; 145 a += chain->buffer_len; 146 u += chain->off; 147 if (chain->next && chain->next->off) 148 w += (size_t)(chain->buffer_len - (chain->misalign + chain->off)); 149 chain = chain->next; 150 } 151 /* subsequent nonempty chains */ 152 while (chain && chain->off) { 153 ++n; 154 a += chain->buffer_len; 155 w += (size_t)chain->misalign; 156 u += chain->off; 157 if (chain->next && chain->next->off) 158 w += (size_t) (chain->buffer_len - (chain->misalign + chain->off)); 159 chain = chain->next; 160 } 161 /* subsequent empty chains */ 162 while (chain) { 163 ++n; 164 a += chain->buffer_len; 165 } 166 *allocatedp = a; 167 *wastedp = w; 168 *usedp = u; 169 } 170 171 #define evbuffer_validate(buf) \ 172 TT_STMT_BEGIN if (!evbuffer_validate_(buf)) TT_DIE(("Buffer format invalid")); TT_STMT_END 173 174 static void 175 test_evbuffer(void *ptr) 176 { 177 static char buffer[512], *tmp; 178 struct evbuffer *evb = evbuffer_new(); 179 struct evbuffer *evb_two = evbuffer_new(); 180 size_t sz_tmp; 181 int i; 182 183 evbuffer_validate(evb); 184 evbuffer_add_printf(evb, "%s/%d", "hello", 1); 185 evbuffer_validate(evb); 186 187 tt_assert(evbuffer_get_length(evb) == 7); 188 tt_assert(!memcmp((char*)EVBUFFER_DATA(evb), "hello/1", 1)); 189 190 evbuffer_add_buffer(evb, evb_two); 191 evbuffer_validate(evb); 192 193 evbuffer_drain(evb, strlen("hello/")); 194 evbuffer_validate(evb); 195 tt_assert(evbuffer_get_length(evb) == 1); 196 tt_assert(!memcmp((char*)EVBUFFER_DATA(evb), "1", 1)); 197 198 evbuffer_add_printf(evb_two, "%s", "/hello"); 199 evbuffer_validate(evb); 200 evbuffer_add_buffer(evb, evb_two); 201 evbuffer_validate(evb); 202 203 tt_assert(evbuffer_get_length(evb_two) == 0); 204 tt_assert(evbuffer_get_length(evb) == 7); 205 tt_assert(!memcmp((char*)EVBUFFER_DATA(evb), "1/hello", 7)); 206 207 memset(buffer, 0, sizeof(buffer)); 208 evbuffer_add(evb, buffer, sizeof(buffer)); 209 evbuffer_validate(evb); 210 tt_assert(evbuffer_get_length(evb) == 7 + 512); 211 212 tmp = (char *)evbuffer_pullup(evb, 7 + 512); 213 tt_assert(tmp); 214 tt_assert(!strncmp(tmp, "1/hello", 7)); 215 tt_assert(!memcmp(tmp + 7, buffer, sizeof(buffer))); 216 evbuffer_validate(evb); 217 218 evbuffer_prepend(evb, "something", 9); 219 evbuffer_validate(evb); 220 evbuffer_prepend(evb, "else", 4); 221 evbuffer_validate(evb); 222 223 tmp = (char *)evbuffer_pullup(evb, 4 + 9 + 7); 224 tt_assert(!strncmp(tmp, "elsesomething1/hello", 4 + 9 + 7)); 225 evbuffer_validate(evb); 226 227 evbuffer_drain(evb, -1); 228 evbuffer_validate(evb); 229 evbuffer_drain(evb_two, -1); 230 evbuffer_validate(evb); 231 232 for (i = 0; i < 3; ++i) { 233 evbuffer_add(evb_two, buffer, sizeof(buffer)); 234 evbuffer_validate(evb_two); 235 evbuffer_add_buffer(evb, evb_two); 236 evbuffer_validate(evb); 237 evbuffer_validate(evb_two); 238 } 239 240 tt_assert(evbuffer_get_length(evb_two) == 0); 241 tt_assert(evbuffer_get_length(evb) == i * sizeof(buffer)); 242 243 /* test remove buffer */ 244 sz_tmp = (size_t)(sizeof(buffer)*2.5); 245 evbuffer_remove_buffer(evb, evb_two, sz_tmp); 246 tt_assert(evbuffer_get_length(evb_two) == sz_tmp); 247 tt_assert(evbuffer_get_length(evb) == sizeof(buffer) / 2); 248 evbuffer_validate(evb); 249 250 if (memcmp(evbuffer_pullup( 251 evb, -1), buffer, sizeof(buffer) / 2) != 0 || 252 memcmp(evbuffer_pullup( 253 evb_two, -1), buffer, sizeof(buffer)) != 0) 254 tt_abort_msg("Pullup did not preserve content"); 255 256 evbuffer_validate(evb); 257 258 259 /* testing one-vector reserve and commit */ 260 { 261 struct evbuffer_iovec v[1]; 262 char *buf; 263 int i, j, r; 264 265 for (i = 0; i < 3; ++i) { 266 r = evbuffer_reserve_space(evb, 10000, v, 1); 267 tt_int_op(r, ==, 1); 268 tt_assert(v[0].iov_len >= 10000); 269 tt_assert(v[0].iov_base != NULL); 270 271 evbuffer_validate(evb); 272 buf = v[0].iov_base; 273 for (j = 0; j < 10000; ++j) { 274 buf[j] = j; 275 } 276 evbuffer_validate(evb); 277 278 tt_int_op(evbuffer_commit_space(evb, v, 1), ==, 0); 279 evbuffer_validate(evb); 280 281 tt_assert(evbuffer_get_length(evb) >= 10000); 282 283 evbuffer_drain(evb, j * 5000); 284 evbuffer_validate(evb); 285 } 286 } 287 288 end: 289 evbuffer_free(evb); 290 evbuffer_free(evb_two); 291 } 292 293 static void 294 no_cleanup(const void *data, size_t datalen, void *extra) 295 { 296 } 297 298 static void 299 test_evbuffer_remove_buffer_with_empty(void *ptr) 300 { 301 struct evbuffer *src = evbuffer_new(); 302 struct evbuffer *dst = evbuffer_new(); 303 char buf[2] = { 'A', 'A' }; 304 305 evbuffer_validate(src); 306 evbuffer_validate(dst); 307 308 /* setup the buffers */ 309 /* we need more data in src than we will move later */ 310 evbuffer_add_reference(src, buf, sizeof(buf), no_cleanup, NULL); 311 evbuffer_add_reference(src, buf, sizeof(buf), no_cleanup, NULL); 312 /* we need one buffer in dst and one empty buffer at the end */ 313 evbuffer_add(dst, buf, sizeof(buf)); 314 evbuffer_add_reference(dst, buf, 0, no_cleanup, NULL); 315 316 evbuffer_validate(src); 317 evbuffer_validate(dst); 318 319 tt_mem_op(evbuffer_pullup(src, -1), ==, "AAAA", 4); 320 tt_mem_op(evbuffer_pullup(dst, -1), ==, "AA", 2); 321 322 /* move three bytes over */ 323 evbuffer_remove_buffer(src, dst, 3); 324 325 evbuffer_validate(src); 326 evbuffer_validate(dst); 327 328 tt_mem_op(evbuffer_pullup(src, -1), ==, "A", 1); 329 tt_mem_op(evbuffer_pullup(dst, -1), ==, "AAAAA", 5); 330 331 end: 332 evbuffer_free(src); 333 evbuffer_free(dst); 334 } 335 336 static void 337 test_evbuffer_remove_buffer_with_empty2(void *ptr) 338 { 339 struct evbuffer *src = evbuffer_new(); 340 struct evbuffer *dst = evbuffer_new(); 341 struct evbuffer *buf = evbuffer_new(); 342 343 evbuffer_add(buf, "foo", 3); 344 evbuffer_add_reference(buf, "foo", 3, NULL, NULL); 345 346 evbuffer_add_reference(src, "foo", 3, NULL, NULL); 347 evbuffer_add_reference(src, NULL, 0, NULL, NULL); 348 evbuffer_add_buffer(src, buf); 349 350 evbuffer_add(buf, "foo", 3); 351 evbuffer_add_reference(buf, "foo", 3, NULL, NULL); 352 353 evbuffer_add_reference(dst, "foo", 3, NULL, NULL); 354 evbuffer_add_reference(dst, NULL, 0, NULL, NULL); 355 evbuffer_add_buffer(dst, buf); 356 357 tt_int_op(evbuffer_get_length(src), ==, 9); 358 tt_int_op(evbuffer_get_length(dst), ==, 9); 359 360 evbuffer_validate(src); 361 evbuffer_validate(dst); 362 363 tt_mem_op(evbuffer_pullup(src, -1), ==, "foofoofoo", 9); 364 tt_mem_op(evbuffer_pullup(dst, -1), ==, "foofoofoo", 9); 365 366 evbuffer_remove_buffer(src, dst, 8); 367 368 evbuffer_validate(src); 369 evbuffer_validate(dst); 370 371 tt_int_op(evbuffer_get_length(src), ==, 1); 372 tt_int_op(evbuffer_get_length(dst), ==, 17); 373 374 tt_mem_op(evbuffer_pullup(src, -1), ==, "o", 1); 375 tt_mem_op(evbuffer_pullup(dst, -1), ==, "foofoofoofoofoofo", 17); 376 377 end: 378 evbuffer_free(src); 379 evbuffer_free(dst); 380 evbuffer_free(buf); 381 } 382 383 static void 384 test_evbuffer_remove_buffer_with_empty3(void *ptr) 385 { 386 struct evbuffer *src = evbuffer_new(); 387 struct evbuffer *dst = evbuffer_new(); 388 struct evbuffer *buf = evbuffer_new(); 389 390 evbuffer_add(buf, "foo", 3); 391 evbuffer_add_reference(buf, NULL, 0, NULL, NULL); 392 393 evbuffer_add_reference(src, "foo", 3, NULL, NULL); 394 evbuffer_add_reference(src, NULL, 0, NULL, NULL); 395 evbuffer_prepend_buffer(src, buf); 396 397 evbuffer_add(buf, "foo", 3); 398 evbuffer_add_reference(buf, NULL, 0, NULL, NULL); 399 400 evbuffer_add_reference(dst, "foo", 3, NULL, NULL); 401 evbuffer_add_reference(dst, NULL, 0, NULL, NULL); 402 evbuffer_prepend_buffer(dst, buf); 403 404 tt_int_op(evbuffer_get_length(src), ==, 6); 405 tt_int_op(evbuffer_get_length(dst), ==, 6); 406 407 evbuffer_validate(src); 408 evbuffer_validate(dst); 409 410 tt_mem_op(evbuffer_pullup(src, -1), ==, "foofoo", 6); 411 tt_mem_op(evbuffer_pullup(dst, -1), ==, "foofoo", 6); 412 413 evbuffer_remove_buffer(src, dst, 5); 414 415 evbuffer_validate(src); 416 evbuffer_validate(dst); 417 418 tt_int_op(evbuffer_get_length(src), ==, 1); 419 tt_int_op(evbuffer_get_length(dst), ==, 11); 420 421 tt_mem_op(evbuffer_pullup(src, -1), ==, "o", 1); 422 tt_mem_op(evbuffer_pullup(dst, -1), ==, "foofoofoofo", 11); 423 424 end: 425 evbuffer_free(src); 426 evbuffer_free(dst); 427 evbuffer_free(buf); 428 } 429 430 static void 431 test_evbuffer_pullup_with_empty(void *ptr) 432 { 433 struct evbuffer *buf = NULL; 434 435 buf = evbuffer_new(); 436 evbuffer_add(buf, "foo", 3); 437 evbuffer_add_reference(buf, NULL, 0, NULL, NULL); 438 evbuffer_validate(buf); 439 tt_int_op(evbuffer_get_length(buf), ==, 3); 440 tt_mem_op(evbuffer_pullup(buf, -1), ==, "foo", 3); 441 442 evbuffer_free(buf); 443 buf = evbuffer_new(); 444 evbuffer_validate(buf); 445 tt_int_op(evbuffer_get_length(buf), ==, 0); 446 tt_int_op(evbuffer_pullup(buf, -1), ==, NULL); 447 448 evbuffer_free(buf); 449 buf = evbuffer_new(); 450 evbuffer_add(buf, "foo", 3); 451 evbuffer_add_reference(buf, NULL, 0, NULL, NULL); 452 evbuffer_validate(buf); 453 tt_mem_op(evbuffer_pullup(buf, 3), ==, "foo", 3); 454 455 end: 456 if (buf) 457 evbuffer_free(buf); 458 } 459 460 static void 461 test_evbuffer_remove_buffer_with_empty_front(void *ptr) 462 { 463 struct evbuffer *buf1 = NULL, *buf2 = NULL; 464 465 buf1 = evbuffer_new(); 466 tt_assert(buf1); 467 468 buf2 = evbuffer_new(); 469 tt_assert(buf2); 470 471 tt_int_op(evbuffer_add_reference(buf1, "foo", 3, NULL, NULL), ==, 0); 472 tt_int_op(evbuffer_prepend(buf1, "", 0), ==, 0); 473 tt_int_op(evbuffer_remove_buffer(buf1, buf2, 1), ==, 1); 474 tt_int_op(evbuffer_add(buf1, "bar", 3), ==, 0); 475 tt_mem_op(evbuffer_pullup(buf1, -1), ==, "oobar", 5); 476 477 evbuffer_validate(buf1); 478 evbuffer_validate(buf2); 479 480 end: 481 if (buf1) 482 evbuffer_free(buf1); 483 if (buf2) 484 evbuffer_free(buf2); 485 } 486 487 static void 488 test_evbuffer_remove_buffer_adjust_last_with_datap_with_empty(void *ptr) 489 { 490 struct evbuffer *buf1 = NULL, *buf2 = NULL; 491 492 buf1 = evbuffer_new(); 493 tt_assert(buf1); 494 495 buf2 = evbuffer_new(); 496 tt_assert(buf2); 497 498 tt_int_op(evbuffer_add(buf1, "aaaaaa", 6), ==, 0); 499 500 // buf1: aaaaaab 501 // buf2: 502 { 503 struct evbuffer_iovec iovecs[2]; 504 /** we want two chains, to leave one chain empty */ 505 tt_int_op(evbuffer_reserve_space(buf1, 971, iovecs, 2), ==, 2); 506 tt_int_op(iovecs[0].iov_len, >=, 1); 507 tt_int_op(iovecs[1].iov_len, >=, 1); 508 tt_assert(*(char *)(iovecs[0].iov_base) = 'b'); 509 tt_assert(iovecs[0].iov_len = 1); 510 tt_int_op(evbuffer_commit_space(buf1, iovecs, 1), ==, 0); 511 } 512 513 // buf1: aaaaaab 514 // buf2: dddcc 515 tt_int_op(evbuffer_add(buf2, "cc", 2), ==, 0); 516 tt_int_op(evbuffer_prepend(buf2, "ddd", 3), ==, 0); 517 518 // buf1: 519 // buf2: aaaaaabdddcc 520 tt_int_op(evbuffer_prepend_buffer(buf2, buf1), ==, 0); 521 522 // buf1: aaaaaabdddcc 523 // buf2: 524 tt_int_op(evbuffer_add_buffer(buf1, buf2), ==, 0); 525 526 // buf1: c 527 // buf2: aaaaaabdddc 528 tt_int_op(evbuffer_remove_buffer(buf1, buf2, 11), ==, 11); 529 530 // This fails today, we observe "aaaaaabcddd" instead! 531 tt_mem_op(evbuffer_pullup(buf2, -1), ==, "aaaaaabdddc", 11); 532 533 evbuffer_validate(buf1); 534 evbuffer_validate(buf2); 535 536 end: 537 if (buf1) 538 evbuffer_free(buf1); 539 if (buf2) 540 evbuffer_free(buf2); 541 } 542 543 static void 544 test_evbuffer_add_buffer_with_empty(void *ptr) 545 { 546 struct evbuffer *src = evbuffer_new(); 547 struct evbuffer *dst = evbuffer_new(); 548 struct evbuffer *buf = evbuffer_new(); 549 550 evbuffer_add(buf, "foo", 3); 551 552 evbuffer_add_reference(src, "foo", 3, NULL, NULL); 553 evbuffer_add_reference(src, NULL, 0, NULL, NULL); 554 evbuffer_add_buffer(src, buf); 555 556 evbuffer_add(buf, "foo", 3); 557 558 evbuffer_add_reference(dst, "foo", 3, NULL, NULL); 559 evbuffer_add_reference(dst, NULL, 0, NULL, NULL); 560 evbuffer_add_buffer(dst, buf); 561 562 tt_int_op(evbuffer_get_length(src), ==, 6); 563 tt_int_op(evbuffer_get_length(dst), ==, 6); 564 565 evbuffer_validate(src); 566 evbuffer_validate(dst); 567 568 end: 569 evbuffer_free(src); 570 evbuffer_free(dst); 571 evbuffer_free(buf); 572 } 573 574 static void 575 test_evbuffer_add_buffer_with_empty2(void *ptr) 576 { 577 struct evbuffer *src = evbuffer_new(); 578 struct evbuffer *dst = evbuffer_new(); 579 struct evbuffer *buf = evbuffer_new(); 580 581 evbuffer_add(buf, "foo", 3); 582 583 evbuffer_add_reference(src, NULL, 0, NULL, NULL); 584 evbuffer_add_buffer(src, buf); 585 586 evbuffer_add(buf, "foo", 3); 587 588 evbuffer_add_reference(dst, NULL, 0, NULL, NULL); 589 evbuffer_add_buffer(dst, buf); 590 591 tt_int_op(evbuffer_get_length(src), ==, 3); 592 tt_int_op(evbuffer_get_length(dst), ==, 3); 593 594 evbuffer_validate(src); 595 evbuffer_validate(dst); 596 597 end: 598 evbuffer_free(src); 599 evbuffer_free(dst); 600 evbuffer_free(buf); 601 } 602 603 static void 604 test_evbuffer_reserve2(void *ptr) 605 { 606 /* Test the two-vector cases of reserve/commit. */ 607 struct evbuffer *buf = evbuffer_new(); 608 int n, i; 609 struct evbuffer_iovec v[2]; 610 size_t remaining; 611 char *cp, *cp2; 612 613 /* First chunk will necessarily be one chunk. Use 512 bytes of it.*/ 614 n = evbuffer_reserve_space(buf, 1024, v, 2); 615 tt_int_op(n, ==, 1); 616 tt_int_op(evbuffer_get_length(buf), ==, 0); 617 tt_assert(v[0].iov_base != NULL); 618 tt_int_op(v[0].iov_len, >=, 1024); 619 memset(v[0].iov_base, 'X', 512); 620 cp = v[0].iov_base; 621 remaining = v[0].iov_len - 512; 622 v[0].iov_len = 512; 623 evbuffer_validate(buf); 624 tt_int_op(0, ==, evbuffer_commit_space(buf, v, 1)); 625 tt_int_op(evbuffer_get_length(buf), ==, 512); 626 evbuffer_validate(buf); 627 628 /* Ask for another same-chunk request, in an existing chunk. Use 8 629 * bytes of it. */ 630 n = evbuffer_reserve_space(buf, 32, v, 2); 631 tt_int_op(n, ==, 1); 632 tt_assert(cp + 512 == v[0].iov_base); 633 tt_int_op(remaining, ==, v[0].iov_len); 634 memset(v[0].iov_base, 'Y', 8); 635 v[0].iov_len = 8; 636 tt_int_op(0, ==, evbuffer_commit_space(buf, v, 1)); 637 tt_int_op(evbuffer_get_length(buf), ==, 520); 638 remaining -= 8; 639 evbuffer_validate(buf); 640 641 /* Now ask for a request that will be split. Use only one byte of it, 642 though. */ 643 n = evbuffer_reserve_space(buf, remaining+64, v, 2); 644 tt_int_op(n, ==, 2); 645 tt_assert(cp + 520 == v[0].iov_base); 646 tt_int_op(remaining, ==, v[0].iov_len); 647 tt_assert(v[1].iov_base); 648 tt_assert(v[1].iov_len >= 64); 649 cp2 = v[1].iov_base; 650 memset(v[0].iov_base, 'Z', 1); 651 v[0].iov_len = 1; 652 tt_int_op(0, ==, evbuffer_commit_space(buf, v, 1)); 653 tt_int_op(evbuffer_get_length(buf), ==, 521); 654 remaining -= 1; 655 evbuffer_validate(buf); 656 657 /* Now ask for a request that will be split. Use some of the first 658 * part and some of the second. */ 659 n = evbuffer_reserve_space(buf, remaining+64, v, 2); 660 evbuffer_validate(buf); 661 tt_int_op(n, ==, 2); 662 tt_assert(cp + 521 == v[0].iov_base); 663 tt_int_op(remaining, ==, v[0].iov_len); 664 tt_assert(v[1].iov_base == cp2); 665 tt_assert(v[1].iov_len >= 64); 666 memset(v[0].iov_base, 'W', 400); 667 v[0].iov_len = 400; 668 memset(v[1].iov_base, 'x', 60); 669 v[1].iov_len = 60; 670 tt_int_op(0, ==, evbuffer_commit_space(buf, v, 2)); 671 tt_int_op(evbuffer_get_length(buf), ==, 981); 672 evbuffer_validate(buf); 673 674 /* Now peek to make sure stuff got made how we like. */ 675 memset(v,0,sizeof(v)); 676 n = evbuffer_peek(buf, -1, NULL, v, 2); 677 tt_int_op(n, ==, 2); 678 tt_int_op(v[0].iov_len, ==, 921); 679 tt_int_op(v[1].iov_len, ==, 60); 680 681 cp = v[0].iov_base; 682 for (i=0; i<512; ++i) 683 tt_int_op(cp[i], ==, 'X'); 684 for (i=512; i<520; ++i) 685 tt_int_op(cp[i], ==, 'Y'); 686 for (i=520; i<521; ++i) 687 tt_int_op(cp[i], ==, 'Z'); 688 for (i=521; i<921; ++i) 689 tt_int_op(cp[i], ==, 'W'); 690 691 cp = v[1].iov_base; 692 for (i=0; i<60; ++i) 693 tt_int_op(cp[i], ==, 'x'); 694 695 end: 696 evbuffer_free(buf); 697 } 698 699 static void 700 test_evbuffer_reserve_many(void *ptr) 701 { 702 /* This is a glass-box test to handle expanding a buffer with more 703 * chunks and reallocating chunks as needed */ 704 struct evbuffer *buf = evbuffer_new(); 705 struct evbuffer_iovec v[8]; 706 int n; 707 size_t sz; 708 int add_data = ptr && !strcmp(ptr, "add"); 709 int fill_first = ptr && !strcmp(ptr, "fill"); 710 char *cp1, *cp2; 711 712 /* When reserving the the first chunk, we just allocate it */ 713 n = evbuffer_reserve_space(buf, 128, v, 2); 714 evbuffer_validate(buf); 715 tt_int_op(n, ==, 1); 716 tt_assert(v[0].iov_len >= 128); 717 sz = v[0].iov_len; 718 cp1 = v[0].iov_base; 719 if (add_data) { 720 *(char*)v[0].iov_base = 'X'; 721 v[0].iov_len = 1; 722 n = evbuffer_commit_space(buf, v, 1); 723 tt_int_op(n, ==, 0); 724 } else if (fill_first) { 725 memset(v[0].iov_base, 'X', v[0].iov_len); 726 n = evbuffer_commit_space(buf, v, 1); 727 tt_int_op(n, ==, 0); 728 n = evbuffer_reserve_space(buf, 128, v, 2); 729 tt_int_op(n, ==, 1); 730 sz = v[0].iov_len; 731 tt_assert(v[0].iov_base != cp1); 732 cp1 = v[0].iov_base; 733 } 734 735 /* Make another chunk get added. */ 736 n = evbuffer_reserve_space(buf, sz+128, v, 2); 737 evbuffer_validate(buf); 738 tt_int_op(n, ==, 2); 739 sz = v[0].iov_len + v[1].iov_len; 740 tt_int_op(sz, >=, v[0].iov_len+128); 741 if (add_data) { 742 tt_assert(v[0].iov_base == cp1 + 1); 743 } else { 744 tt_assert(v[0].iov_base == cp1); 745 } 746 cp1 = v[0].iov_base; 747 cp2 = v[1].iov_base; 748 749 /* And a third chunk. */ 750 n = evbuffer_reserve_space(buf, sz+128, v, 3); 751 evbuffer_validate(buf); 752 tt_int_op(n, ==, 3); 753 tt_assert(cp1 == v[0].iov_base); 754 tt_assert(cp2 == v[1].iov_base); 755 sz = v[0].iov_len + v[1].iov_len + v[2].iov_len; 756 757 /* Now force a reallocation by asking for more space in only 2 758 * buffers. */ 759 n = evbuffer_reserve_space(buf, sz+128, v, 2); 760 evbuffer_validate(buf); 761 if (add_data) { 762 tt_int_op(n, ==, 2); 763 tt_assert(cp1 == v[0].iov_base); 764 } else { 765 tt_int_op(n, ==, 1); 766 } 767 768 end: 769 evbuffer_free(buf); 770 } 771 772 static void 773 test_evbuffer_reserve_with_empty(void *ptr) 774 { 775 struct evbuffer *buf; 776 struct evbuffer_iovec v[2]; 777 778 tt_assert(buf = evbuffer_new()); 779 evbuffer_add(buf, "a", 1); 780 tt_int_op(evbuffer_reserve_space(buf, 1<<12, v, 2), ==, 2); 781 v[0].iov_len = 1; 782 *(char *)v[0].iov_base = 'b'; 783 tt_int_op(evbuffer_commit_space(buf, v, 1), ==, 0); 784 evbuffer_add(buf, "c", 1); 785 tt_mem_op(evbuffer_pullup(buf, -1), ==, "abc", 2); 786 787 evbuffer_validate(buf); 788 789 end: 790 if (buf) 791 evbuffer_free(buf); 792 } 793 794 /* regression for evbuffer_expand_fast_() with invalid last_with_datap that has 795 * been left after evbuffer_prepend() with empty chain in it */ 796 static void 797 test_evbuffer_reserve_invalid_last_with_datap(void *ptr) 798 { 799 struct evbuffer *buf = NULL; 800 struct evbuffer_iovec vec[2]; 801 const int nvec = ARRAY_SIZE(vec); 802 int i, avec; 803 804 buf = evbuffer_new(); 805 tt_assert(buf); 806 807 /* prepend with an empty chain */ 808 evbuffer_add_reference(buf, "", 0, NULL, NULL); 809 evbuffer_prepend(buf, "foo", 3); 810 /* after invalid last_with_datap will create new chain */ 811 evbuffer_add(buf, "", 0); 812 /* we need to create at least 2 "used" (in evbuffer_expand_fast_()) chains */ 813 tt_int_op(avec = evbuffer_reserve_space(buf, 1<<12, vec, nvec), >=, 1); 814 for (i = 0; i < avec; ++i) 815 vec[i].iov_len = 0; 816 tt_int_op(evbuffer_commit_space(buf, vec, avec), ==, 0); 817 818 /* and an actual problem, that triggers an assert(chain == buf->first) in 819 * evbuffer_expand_fast_() */ 820 tt_int_op(evbuffer_reserve_space(buf, 1<<13, vec, nvec), >=, 1); 821 822 evbuffer_validate(buf); 823 824 end: 825 if (buf) 826 evbuffer_free(buf); 827 } 828 829 static void 830 test_evbuffer_expand(void *ptr) 831 { 832 char data[4096]; 833 struct evbuffer *buf; 834 size_t a,w,u; 835 void *buffer; 836 837 memset(data, 'X', sizeof(data)); 838 839 /* Make sure that expand() works on an empty buffer */ 840 buf = evbuffer_new(); 841 tt_int_op(evbuffer_expand(buf, 20000), ==, 0); 842 evbuffer_validate(buf); 843 a=w=u=0; 844 evbuffer_get_waste(buf, &a,&w,&u); 845 tt_assert(w == 0); 846 tt_assert(u == 0); 847 tt_assert(a >= 20000); 848 tt_assert(buf->first); 849 tt_assert(buf->first == buf->last); 850 tt_assert(buf->first->off == 0); 851 tt_assert(buf->first->buffer_len >= 20000); 852 853 /* Make sure that expand() works as a no-op when there's enough 854 * contiguous space already. */ 855 buffer = buf->first->buffer; 856 evbuffer_add(buf, data, 1024); 857 tt_int_op(evbuffer_expand(buf, 1024), ==, 0); 858 tt_assert(buf->first->buffer == buffer); 859 evbuffer_validate(buf); 860 evbuffer_free(buf); 861 862 /* Make sure that expand() can work by moving misaligned data 863 * when it makes sense to do so. */ 864 buf = evbuffer_new(); 865 evbuffer_add(buf, data, 400); 866 { 867 int n = (int)(buf->first->buffer_len - buf->first->off - 1); 868 tt_assert(n < (int)sizeof(data)); 869 evbuffer_add(buf, data, n); 870 } 871 tt_assert(buf->first == buf->last); 872 tt_assert(buf->first->off == buf->first->buffer_len - 1); 873 evbuffer_drain(buf, buf->first->off - 1); 874 tt_assert(1 == evbuffer_get_length(buf)); 875 tt_assert(buf->first->misalign > 0); 876 tt_assert(buf->first->off == 1); 877 buffer = buf->first->buffer; 878 tt_assert(evbuffer_expand(buf, 40) == 0); 879 tt_assert(buf->first == buf->last); 880 tt_assert(buf->first->off == 1); 881 tt_assert(buf->first->buffer == buffer); 882 tt_assert(buf->first->misalign == 0); 883 evbuffer_validate(buf); 884 evbuffer_free(buf); 885 886 /* add, expand, pull-up: This used to crash libevent. */ 887 buf = evbuffer_new(); 888 889 evbuffer_add(buf, data, sizeof(data)); 890 evbuffer_add(buf, data, sizeof(data)); 891 evbuffer_add(buf, data, sizeof(data)); 892 893 evbuffer_validate(buf); 894 evbuffer_expand(buf, 1024); 895 evbuffer_validate(buf); 896 evbuffer_pullup(buf, -1); 897 evbuffer_validate(buf); 898 899 end: 900 evbuffer_free(buf); 901 } 902 903 static void 904 test_evbuffer_expand_overflow(void *ptr) 905 { 906 struct evbuffer *buf; 907 908 buf = evbuffer_new(); 909 evbuffer_add(buf, "1", 1); 910 evbuffer_expand(buf, EVBUFFER_CHAIN_MAX); 911 evbuffer_validate(buf); 912 913 evbuffer_expand(buf, EV_SIZE_MAX); 914 evbuffer_validate(buf); 915 916 end: 917 evbuffer_free(buf); 918 } 919 920 static void 921 test_evbuffer_add1(void *ptr) 922 { 923 struct evbuffer *buf; 924 char *str; 925 926 buf = evbuffer_new(); 927 evbuffer_add(buf, "1", 1); 928 evbuffer_validate(buf); 929 evbuffer_expand(buf, 2048); 930 evbuffer_validate(buf); 931 evbuffer_add(buf, "2", 1); 932 evbuffer_validate(buf); 933 evbuffer_add_printf(buf, "3"); 934 evbuffer_validate(buf); 935 936 tt_assert(evbuffer_get_length(buf) == 3); 937 str = (char *)evbuffer_pullup(buf, -1); 938 tt_assert(str[0] == '1'); 939 tt_assert(str[1] == '2'); 940 tt_assert(str[2] == '3'); 941 end: 942 evbuffer_free(buf); 943 } 944 945 static void 946 test_evbuffer_add2(void *ptr) 947 { 948 struct evbuffer *buf; 949 static char data[4096]; 950 int data_len = MIN_BUFFER_SIZE-EVBUFFER_CHAIN_SIZE-10; 951 char *str; 952 int len; 953 954 memset(data, 'P', sizeof(data)); 955 buf = evbuffer_new(); 956 evbuffer_add(buf, data, data_len); 957 evbuffer_validate(buf); 958 evbuffer_expand(buf, 100); 959 evbuffer_validate(buf); 960 evbuffer_add(buf, "2", 1); 961 evbuffer_validate(buf); 962 evbuffer_add_printf(buf, "3"); 963 evbuffer_validate(buf); 964 965 len = evbuffer_get_length(buf); 966 tt_assert(len == data_len+2); 967 str = (char *)evbuffer_pullup(buf, -1); 968 tt_assert(str[len-3] == 'P'); 969 tt_assert(str[len-2] == '2'); 970 tt_assert(str[len-1] == '3'); 971 end: 972 evbuffer_free(buf); 973 } 974 975 static int reference_cb_called; 976 static void 977 reference_cb(const void *data, size_t len, void *extra) 978 { 979 tt_str_op(data, ==, "this is what we add as read-only memory."); 980 tt_int_op(len, ==, strlen(data)); 981 tt_want(extra == (void *)0xdeadaffe); 982 ++reference_cb_called; 983 end: 984 ; 985 } 986 987 static void 988 test_evbuffer_reference(void *ptr) 989 { 990 struct evbuffer *src = evbuffer_new(); 991 struct evbuffer *dst = evbuffer_new(); 992 struct evbuffer_iovec v[1]; 993 const char *data = "this is what we add as read-only memory."; 994 reference_cb_called = 0; 995 996 tt_assert(evbuffer_add_reference(src, data, strlen(data), 997 reference_cb, (void *)0xdeadaffe) != -1); 998 999 evbuffer_reserve_space(dst, strlen(data), v, 1); 1000 tt_assert(evbuffer_remove(src, v[0].iov_base, 10) != -1); 1001 1002 evbuffer_validate(src); 1003 evbuffer_validate(dst); 1004 1005 /* make sure that we don't write data at the beginning */ 1006 evbuffer_prepend(src, "aaaaa", 5); 1007 evbuffer_validate(src); 1008 evbuffer_drain(src, 5); 1009 1010 tt_assert(evbuffer_remove(src, ((char*)(v[0].iov_base)) + 10, 1011 strlen(data) - 10) != -1); 1012 1013 v[0].iov_len = strlen(data); 1014 1015 evbuffer_commit_space(dst, v, 1); 1016 evbuffer_validate(src); 1017 evbuffer_validate(dst); 1018 1019 tt_int_op(reference_cb_called, ==, 1); 1020 1021 tt_assert(!memcmp(evbuffer_pullup(dst, strlen(data)), 1022 data, strlen(data))); 1023 evbuffer_validate(dst); 1024 1025 end: 1026 evbuffer_free(dst); 1027 evbuffer_free(src); 1028 } 1029 1030 static void 1031 test_evbuffer_reference2(void *ptr) 1032 { 1033 struct evbuffer *buf; 1034 static char data[4096]; 1035 int data_len = MIN_BUFFER_SIZE-EVBUFFER_CHAIN_SIZE-10; 1036 char *str; 1037 int len; 1038 1039 memset(data, 'P', sizeof(data)); 1040 buf = evbuffer_new(); 1041 evbuffer_add(buf, data, data_len); 1042 evbuffer_validate(buf); 1043 evbuffer_expand(buf, 100); 1044 evbuffer_validate(buf); 1045 evbuffer_add_reference(buf, "2", 1, no_cleanup, NULL); 1046 evbuffer_validate(buf); 1047 evbuffer_add_printf(buf, "3"); 1048 evbuffer_validate(buf); 1049 1050 len = evbuffer_get_length(buf); 1051 tt_assert(len == data_len+2); 1052 str = (char *)evbuffer_pullup(buf, -1); 1053 tt_assert(str[len-3] == 'P'); 1054 tt_assert(str[len-2] == '2'); 1055 tt_assert(str[len-1] == '3'); 1056 end: 1057 evbuffer_free(buf); 1058 } 1059 1060 static struct event_base *addfile_test_event_base; 1061 static int addfile_test_done_writing; 1062 static int addfile_test_total_written; 1063 static int addfile_test_total_read; 1064 1065 static void 1066 addfile_test_writecb(evutil_socket_t fd, short what, void *arg) 1067 { 1068 struct evbuffer *b = arg; 1069 int r; 1070 evbuffer_validate(b); 1071 while (evbuffer_get_length(b)) { 1072 r = evbuffer_write(b, fd); 1073 if (r > 0) { 1074 addfile_test_total_written += r; 1075 TT_BLATHER(("Wrote %d/%d bytes", r, addfile_test_total_written)); 1076 } else { 1077 int e = evutil_socket_geterror(fd); 1078 if (EVUTIL_ERR_RW_RETRIABLE(e)) 1079 return; 1080 tt_fail_perror("write"); 1081 event_base_loopexit(addfile_test_event_base,NULL); 1082 } 1083 evbuffer_validate(b); 1084 } 1085 addfile_test_done_writing = 1; 1086 return; 1087 end: 1088 event_base_loopexit(addfile_test_event_base,NULL); 1089 } 1090 1091 static void 1092 addfile_test_readcb(evutil_socket_t fd, short what, void *arg) 1093 { 1094 struct evbuffer *b = arg; 1095 int e, r = 0; 1096 do { 1097 r = evbuffer_read(b, fd, 1024); 1098 if (r > 0) { 1099 addfile_test_total_read += r; 1100 TT_BLATHER(("Read %d/%d bytes", r, addfile_test_total_read)); 1101 } 1102 } while (r > 0); 1103 if (r < 0) { 1104 e = evutil_socket_geterror(fd); 1105 if (! EVUTIL_ERR_RW_RETRIABLE(e)) { 1106 tt_fail_perror("read"); 1107 event_base_loopexit(addfile_test_event_base,NULL); 1108 } 1109 } 1110 if (addfile_test_done_writing && 1111 addfile_test_total_read >= addfile_test_total_written) { 1112 event_base_loopexit(addfile_test_event_base,NULL); 1113 } 1114 } 1115 1116 static void 1117 test_evbuffer_add_file(void *ptr) 1118 { 1119 struct basic_test_data *testdata = ptr; 1120 const char *impl = testdata->setup_data; 1121 struct evbuffer *src = evbuffer_new(), *dest = evbuffer_new(); 1122 char *tmpfilename = NULL; 1123 char *data = NULL; 1124 const char *expect_data; 1125 size_t datalen, expect_len; 1126 const char *compare; 1127 int fd = -1; 1128 int want_ismapping = -1, want_cansendfile = -1; 1129 unsigned flags = 0; 1130 int use_segment = 1, use_bigfile = 0, map_from_offset = 0, 1131 view_from_offset = 0; 1132 struct evbuffer_file_segment *seg = NULL; 1133 ev_off_t starting_offset = 0, mapping_len = -1; 1134 ev_off_t segment_offset = 0, segment_len = -1; 1135 struct event *rev=NULL, *wev=NULL; 1136 struct event_base *base = testdata->base; 1137 evutil_socket_t pair[2] = {-1, -1}; 1138 struct evutil_weakrand_state seed = { 123456789U }; 1139 1140 /* This test is highly parameterized based on substrings of its 1141 * argument. The strings are: */ 1142 tt_assert(impl); 1143 if (strstr(impl, "nosegment")) { 1144 /* If nosegment is set, use the older evbuffer_add_file 1145 * interface */ 1146 use_segment = 0; 1147 } 1148 if (strstr(impl, "bigfile")) { 1149 /* If bigfile is set, use a 512K file. Else use a smaller 1150 * one. */ 1151 use_bigfile = 1; 1152 } 1153 if (strstr(impl, "map_offset")) { 1154 /* If map_offset is set, we build the file segment starting 1155 * from a point other than byte 0 and ending somewhere other 1156 * than the last byte. Otherwise we map the whole thing */ 1157 map_from_offset = 1; 1158 } 1159 if (strstr(impl, "offset_in_segment")) { 1160 /* If offset_in_segment is set, we add a subsection of the 1161 * file semgment starting from a point other than byte 0 of 1162 * the segment. */ 1163 view_from_offset = 1; 1164 } 1165 if (strstr(impl, "sendfile")) { 1166 /* If sendfile is set, we try to use a sendfile/splice style 1167 * backend. */ 1168 flags = EVBUF_FS_DISABLE_MMAP; 1169 want_cansendfile = 1; 1170 want_ismapping = 0; 1171 } else if (strstr(impl, "mmap")) { 1172 /* If sendfile is set, we try to use a mmap/CreateFileMapping 1173 * style backend. */ 1174 flags = EVBUF_FS_DISABLE_SENDFILE; 1175 want_ismapping = 1; 1176 want_cansendfile = 0; 1177 } else if (strstr(impl, "linear")) { 1178 /* If linear is set, we try to use a read-the-whole-thing 1179 * backend. */ 1180 flags = EVBUF_FS_DISABLE_SENDFILE|EVBUF_FS_DISABLE_MMAP; 1181 want_ismapping = 0; 1182 want_cansendfile = 0; 1183 } else if (strstr(impl, "default")) { 1184 /* The caller doesn't care which backend we use. */ 1185 ; 1186 } else { 1187 /* The caller must choose a backend. */ 1188 TT_DIE(("Didn't recognize the implementation")); 1189 } 1190 1191 if (use_bigfile) { 1192 unsigned int i; 1193 datalen = 1024*512; 1194 data = malloc(1024*512); 1195 tt_assert(data); 1196 for (i = 0; i < datalen; ++i) 1197 data[i] = (char)evutil_weakrand_(&seed); 1198 } else { 1199 data = strdup("here is a relatively small string."); 1200 tt_assert(data); 1201 datalen = strlen(data); 1202 } 1203 1204 fd = regress_make_tmpfile(data, datalen, &tmpfilename); 1205 1206 if (map_from_offset) { 1207 starting_offset = datalen/4 + 1; 1208 mapping_len = datalen / 2 - 1; 1209 expect_data = data + starting_offset; 1210 expect_len = mapping_len; 1211 } else { 1212 expect_data = data; 1213 expect_len = datalen; 1214 } 1215 if (view_from_offset) { 1216 tt_assert(use_segment); /* Can't do this with add_file*/ 1217 segment_offset = expect_len / 3; 1218 segment_len = expect_len / 2; 1219 expect_data = expect_data + segment_offset; 1220 expect_len = segment_len; 1221 } 1222 1223 if (use_segment) { 1224 seg = evbuffer_file_segment_new(fd, starting_offset, 1225 mapping_len, flags); 1226 tt_assert(seg); 1227 if (want_ismapping >= 0) { 1228 if (seg->is_mapping != (unsigned)want_ismapping) 1229 tt_skip(); 1230 } 1231 if (want_cansendfile >= 0) { 1232 if (seg->can_sendfile != (unsigned)want_cansendfile) 1233 tt_skip(); 1234 } 1235 } 1236 1237 /* Say that it drains to a fd so that we can use sendfile. */ 1238 evbuffer_set_flags(src, EVBUFFER_FLAG_DRAINS_TO_FD); 1239 1240 #if defined(EVENT__HAVE_SENDFILE) && defined(__sun__) && defined(__svr4__) 1241 /* We need to use a pair of AF_INET sockets, since Solaris 1242 doesn't support sendfile() over AF_UNIX. */ 1243 if (evutil_ersatz_socketpair_(AF_INET, SOCK_STREAM, 0, pair) == -1) 1244 tt_abort_msg("ersatz_socketpair failed"); 1245 #else 1246 if (evutil_socketpair(AF_UNIX, SOCK_STREAM, 0, pair) == -1) 1247 tt_abort_msg("socketpair failed"); 1248 #endif 1249 evutil_make_socket_nonblocking(pair[0]); 1250 evutil_make_socket_nonblocking(pair[1]); 1251 1252 tt_assert(fd != -1); 1253 1254 if (use_segment) { 1255 tt_assert(evbuffer_add_file_segment(src, seg, 1256 segment_offset, segment_len)!=-1); 1257 } else { 1258 tt_assert(evbuffer_add_file(src, fd, starting_offset, 1259 mapping_len) != -1); 1260 } 1261 1262 evbuffer_validate(src); 1263 1264 addfile_test_event_base = base; 1265 addfile_test_done_writing = 0; 1266 addfile_test_total_written = 0; 1267 addfile_test_total_read = 0; 1268 1269 wev = event_new(base, pair[0], EV_WRITE|EV_PERSIST, 1270 addfile_test_writecb, src); 1271 rev = event_new(base, pair[1], EV_READ|EV_PERSIST, 1272 addfile_test_readcb, dest); 1273 1274 event_add(wev, NULL); 1275 event_add(rev, NULL); 1276 event_base_dispatch(base); 1277 1278 evbuffer_validate(src); 1279 evbuffer_validate(dest); 1280 1281 tt_assert(addfile_test_done_writing); 1282 tt_int_op(addfile_test_total_written, ==, expect_len); 1283 tt_int_op(addfile_test_total_read, ==, expect_len); 1284 1285 compare = (char *)evbuffer_pullup(dest, expect_len); 1286 tt_assert(compare != NULL); 1287 if (memcmp(compare, expect_data, expect_len)) { 1288 tt_abort_msg("Data from add_file differs."); 1289 } 1290 1291 evbuffer_validate(dest); 1292 end: 1293 if (data) 1294 free(data); 1295 if (seg) 1296 evbuffer_file_segment_free(seg); 1297 if (src) 1298 evbuffer_free(src); 1299 if (dest) 1300 evbuffer_free(dest); 1301 if (pair[0] >= 0) 1302 evutil_closesocket(pair[0]); 1303 if (pair[1] >= 0) 1304 evutil_closesocket(pair[1]); 1305 if (wev) 1306 event_free(wev); 1307 if (rev) 1308 event_free(rev); 1309 if (tmpfilename) { 1310 unlink(tmpfilename); 1311 free(tmpfilename); 1312 } 1313 } 1314 1315 static int file_segment_cleanup_cb_called_count = 0; 1316 static struct evbuffer_file_segment const* file_segment_cleanup_cb_called_with = NULL; 1317 static int file_segment_cleanup_cb_called_with_flags = 0; 1318 static void* file_segment_cleanup_cb_called_with_arg = NULL; 1319 static void 1320 file_segment_cleanup_cp(struct evbuffer_file_segment const* seg, int flags, void* arg) 1321 { 1322 ++file_segment_cleanup_cb_called_count; 1323 file_segment_cleanup_cb_called_with = seg; 1324 file_segment_cleanup_cb_called_with_flags = flags; 1325 file_segment_cleanup_cb_called_with_arg = arg; 1326 } 1327 1328 static void 1329 test_evbuffer_file_segment_add_cleanup_cb(void* ptr) 1330 { 1331 char *tmpfilename = NULL; 1332 int fd = -1; 1333 struct evbuffer *evb = NULL; 1334 struct evbuffer_file_segment *seg = NULL, *segptr; 1335 char const* arg = "token"; 1336 1337 fd = regress_make_tmpfile("file_segment_test_file", 22, &tmpfilename); 1338 tt_int_op(fd, >=, 0); 1339 1340 evb = evbuffer_new(); 1341 tt_assert(evb); 1342 1343 segptr = seg = evbuffer_file_segment_new(fd, 0, -1, 0); 1344 tt_assert(seg); 1345 1346 evbuffer_file_segment_add_cleanup_cb( 1347 seg, &file_segment_cleanup_cp, (void*)arg); 1348 1349 tt_assert(fd != -1); 1350 1351 tt_assert(evbuffer_add_file_segment(evb, seg, 0, -1)!=-1); 1352 1353 evbuffer_validate(evb); 1354 1355 tt_int_op(file_segment_cleanup_cb_called_count, ==, 0); 1356 evbuffer_file_segment_free(seg); 1357 seg = NULL; /* Prevent double-free. */ 1358 1359 tt_int_op(file_segment_cleanup_cb_called_count, ==, 0); 1360 evbuffer_free(evb); 1361 evb = NULL; /* pevent double-free */ 1362 1363 tt_int_op(file_segment_cleanup_cb_called_count, ==, 1); 1364 tt_assert(file_segment_cleanup_cb_called_with == segptr); 1365 tt_assert(file_segment_cleanup_cb_called_with_flags == 0); 1366 tt_assert(file_segment_cleanup_cb_called_with_arg == (void*)arg); 1367 1368 end: 1369 if (evb) 1370 evbuffer_free(evb); 1371 if (seg) 1372 evbuffer_file_segment_free(seg); 1373 if (tmpfilename) { 1374 unlink(tmpfilename); 1375 free(tmpfilename); 1376 } 1377 } 1378 1379 #ifndef EVENT__DISABLE_MM_REPLACEMENT 1380 static void * 1381 failing_malloc(size_t how_much) 1382 { 1383 errno = ENOMEM; 1384 return NULL; 1385 } 1386 #endif 1387 1388 static void 1389 test_evbuffer_readln(void *ptr) 1390 { 1391 struct evbuffer *evb = evbuffer_new(); 1392 struct evbuffer *evb_tmp = evbuffer_new(); 1393 const char *s; 1394 char *cp = NULL; 1395 size_t sz; 1396 1397 #define tt_line_eq(content) \ 1398 TT_STMT_BEGIN \ 1399 if (!cp || sz != strlen(content) || strcmp(cp, content)) { \ 1400 TT_DIE(("Wanted %s; got %s [%d]", content, cp, (int)sz)); \ 1401 } \ 1402 TT_STMT_END 1403 1404 /* Test EOL_ANY. */ 1405 s = "complex silly newline\r\n\n\r\n\n\rmore\0\n"; 1406 evbuffer_add(evb, s, strlen(s)+2); 1407 evbuffer_validate(evb); 1408 cp = evbuffer_readln(evb, &sz, EVBUFFER_EOL_ANY); 1409 tt_line_eq("complex silly newline"); 1410 free(cp); 1411 evbuffer_validate(evb); 1412 cp = evbuffer_readln(evb, &sz, EVBUFFER_EOL_ANY); 1413 if (!cp || sz != 5 || memcmp(cp, "more\0\0", 6)) 1414 tt_abort_msg("Not as expected"); 1415 tt_uint_op(evbuffer_get_length(evb), ==, 0); 1416 evbuffer_validate(evb); 1417 s = "\nno newline"; 1418 evbuffer_add(evb, s, strlen(s)); 1419 free(cp); 1420 evbuffer_validate(evb); 1421 cp = evbuffer_readln(evb, &sz, EVBUFFER_EOL_ANY); 1422 tt_line_eq(""); 1423 free(cp); 1424 evbuffer_validate(evb); 1425 cp = evbuffer_readln(evb, &sz, EVBUFFER_EOL_ANY); 1426 tt_assert(!cp); 1427 evbuffer_validate(evb); 1428 evbuffer_drain(evb, evbuffer_get_length(evb)); 1429 tt_assert(evbuffer_get_length(evb) == 0); 1430 evbuffer_validate(evb); 1431 1432 /* Test EOL_CRLF */ 1433 s = "Line with\rin the middle\nLine with good crlf\r\n\nfinal\n"; 1434 evbuffer_add(evb, s, strlen(s)); 1435 evbuffer_validate(evb); 1436 cp = evbuffer_readln(evb, &sz, EVBUFFER_EOL_CRLF); 1437 tt_line_eq("Line with\rin the middle"); 1438 free(cp); 1439 evbuffer_validate(evb); 1440 1441 cp = evbuffer_readln(evb, &sz, EVBUFFER_EOL_CRLF); 1442 tt_line_eq("Line with good crlf"); 1443 free(cp); 1444 evbuffer_validate(evb); 1445 1446 cp = evbuffer_readln(evb, &sz, EVBUFFER_EOL_CRLF); 1447 tt_line_eq(""); 1448 free(cp); 1449 evbuffer_validate(evb); 1450 1451 cp = evbuffer_readln(evb, &sz, EVBUFFER_EOL_CRLF); 1452 tt_line_eq("final"); 1453 s = "x"; 1454 evbuffer_validate(evb); 1455 evbuffer_add(evb, s, 1); 1456 evbuffer_validate(evb); 1457 free(cp); 1458 cp = evbuffer_readln(evb, &sz, EVBUFFER_EOL_CRLF); 1459 tt_assert(!cp); 1460 evbuffer_validate(evb); 1461 1462 /* Test CRLF_STRICT */ 1463 s = " and a bad crlf\nand a good one\r\n\r\nMore\r"; 1464 evbuffer_add(evb, s, strlen(s)); 1465 evbuffer_validate(evb); 1466 cp = evbuffer_readln(evb, &sz, EVBUFFER_EOL_CRLF_STRICT); 1467 tt_line_eq("x and a bad crlf\nand a good one"); 1468 free(cp); 1469 evbuffer_validate(evb); 1470 1471 cp = evbuffer_readln(evb, &sz, EVBUFFER_EOL_CRLF_STRICT); 1472 tt_line_eq(""); 1473 free(cp); 1474 evbuffer_validate(evb); 1475 1476 cp = evbuffer_readln(evb, &sz, EVBUFFER_EOL_CRLF_STRICT); 1477 tt_assert(!cp); 1478 evbuffer_validate(evb); 1479 evbuffer_add(evb, "\n", 1); 1480 evbuffer_validate(evb); 1481 1482 cp = evbuffer_readln(evb, &sz, EVBUFFER_EOL_CRLF_STRICT); 1483 tt_line_eq("More"); 1484 free(cp); 1485 tt_assert(evbuffer_get_length(evb) == 0); 1486 evbuffer_validate(evb); 1487 1488 s = "An internal CR\r is not an eol\r\nNor is a lack of one"; 1489 evbuffer_add(evb, s, strlen(s)); 1490 cp = evbuffer_readln(evb, &sz, EVBUFFER_EOL_CRLF_STRICT); 1491 tt_line_eq("An internal CR\r is not an eol"); 1492 free(cp); 1493 evbuffer_validate(evb); 1494 1495 cp = evbuffer_readln(evb, &sz, EVBUFFER_EOL_CRLF_STRICT); 1496 tt_assert(!cp); 1497 evbuffer_validate(evb); 1498 1499 evbuffer_add(evb, "\r\n", 2); 1500 evbuffer_validate(evb); 1501 cp = evbuffer_readln(evb, &sz, EVBUFFER_EOL_CRLF_STRICT); 1502 tt_line_eq("Nor is a lack of one"); 1503 free(cp); 1504 tt_assert(evbuffer_get_length(evb) == 0); 1505 evbuffer_validate(evb); 1506 1507 /* Test LF */ 1508 s = "An\rand a nl\n\nText"; 1509 evbuffer_add(evb, s, strlen(s)); 1510 evbuffer_validate(evb); 1511 1512 cp = evbuffer_readln(evb, &sz, EVBUFFER_EOL_LF); 1513 tt_line_eq("An\rand a nl"); 1514 free(cp); 1515 evbuffer_validate(evb); 1516 1517 cp = evbuffer_readln(evb, &sz, EVBUFFER_EOL_LF); 1518 tt_line_eq(""); 1519 free(cp); 1520 evbuffer_validate(evb); 1521 1522 cp = evbuffer_readln(evb, &sz, EVBUFFER_EOL_LF); 1523 tt_assert(!cp); 1524 free(cp); 1525 evbuffer_add(evb, "\n", 1); 1526 evbuffer_validate(evb); 1527 cp = evbuffer_readln(evb, &sz, EVBUFFER_EOL_LF); 1528 tt_line_eq("Text"); 1529 free(cp); 1530 evbuffer_validate(evb); 1531 1532 /* Test NUL */ 1533 tt_int_op(evbuffer_get_length(evb), ==, 0); 1534 { 1535 char x[] = 1536 "NUL\n\0\0" 1537 "The all-zeros character which may serve\0" 1538 "to accomplish time fill\0and media fill"; 1539 /* Add all but the final NUL of x. */ 1540 evbuffer_add(evb, x, sizeof(x)-1); 1541 } 1542 cp = evbuffer_readln(evb, &sz, EVBUFFER_EOL_NUL); 1543 tt_line_eq("NUL\n"); 1544 free(cp); 1545 cp = evbuffer_readln(evb, &sz, EVBUFFER_EOL_NUL); 1546 tt_line_eq(""); 1547 free(cp); 1548 cp = evbuffer_readln(evb, &sz, EVBUFFER_EOL_NUL); 1549 tt_line_eq("The all-zeros character which may serve"); 1550 free(cp); 1551 cp = evbuffer_readln(evb, &sz, EVBUFFER_EOL_NUL); 1552 tt_line_eq("to accomplish time fill"); 1553 free(cp); 1554 cp = evbuffer_readln(evb, &sz, EVBUFFER_EOL_NUL); 1555 tt_ptr_op(cp, ==, NULL); 1556 evbuffer_drain(evb, -1); 1557 1558 /* Test CRLF_STRICT - across boundaries*/ 1559 s = " and a bad crlf\nand a good one\r"; 1560 evbuffer_add(evb_tmp, s, strlen(s)); 1561 evbuffer_validate(evb); 1562 evbuffer_add_buffer(evb, evb_tmp); 1563 evbuffer_validate(evb); 1564 s = "\n\r"; 1565 evbuffer_add(evb_tmp, s, strlen(s)); 1566 evbuffer_validate(evb); 1567 evbuffer_add_buffer(evb, evb_tmp); 1568 evbuffer_validate(evb); 1569 s = "\nMore\r"; 1570 evbuffer_add(evb_tmp, s, strlen(s)); 1571 evbuffer_validate(evb); 1572 evbuffer_add_buffer(evb, evb_tmp); 1573 evbuffer_validate(evb); 1574 1575 cp = evbuffer_readln(evb, &sz, EVBUFFER_EOL_CRLF_STRICT); 1576 tt_line_eq(" and a bad crlf\nand a good one"); 1577 free(cp); 1578 evbuffer_validate(evb); 1579 1580 cp = evbuffer_readln(evb, &sz, EVBUFFER_EOL_CRLF_STRICT); 1581 tt_line_eq(""); 1582 free(cp); 1583 evbuffer_validate(evb); 1584 1585 cp = evbuffer_readln(evb, &sz, EVBUFFER_EOL_CRLF_STRICT); 1586 tt_assert(!cp); 1587 free(cp); 1588 evbuffer_validate(evb); 1589 evbuffer_add(evb, "\n", 1); 1590 evbuffer_validate(evb); 1591 cp = evbuffer_readln(evb, &sz, EVBUFFER_EOL_CRLF_STRICT); 1592 tt_line_eq("More"); 1593 free(cp); cp = NULL; 1594 evbuffer_validate(evb); 1595 tt_assert(evbuffer_get_length(evb) == 0); 1596 1597 /* Test memory problem*/ 1598 s = "one line\ntwo line\nblue line"; 1599 evbuffer_add(evb_tmp, s, strlen(s)); 1600 evbuffer_validate(evb); 1601 evbuffer_add_buffer(evb, evb_tmp); 1602 evbuffer_validate(evb); 1603 1604 cp = evbuffer_readln(evb, &sz, EVBUFFER_EOL_LF); 1605 tt_line_eq("one line"); 1606 free(cp); cp = NULL; 1607 evbuffer_validate(evb); 1608 1609 /* the next call to readline should fail */ 1610 #ifndef EVENT__DISABLE_MM_REPLACEMENT 1611 event_set_mem_functions(failing_malloc, realloc, free); 1612 cp = evbuffer_readln(evb, &sz, EVBUFFER_EOL_LF); 1613 tt_assert(cp == NULL); 1614 evbuffer_validate(evb); 1615 1616 /* now we should get the next line back */ 1617 event_set_mem_functions(malloc, realloc, free); 1618 #endif 1619 cp = evbuffer_readln(evb, &sz, EVBUFFER_EOL_LF); 1620 tt_line_eq("two line"); 1621 free(cp); cp = NULL; 1622 evbuffer_validate(evb); 1623 1624 end: 1625 evbuffer_free(evb); 1626 evbuffer_free(evb_tmp); 1627 if (cp) free(cp); 1628 } 1629 1630 static void 1631 test_evbuffer_search_eol(void *ptr) 1632 { 1633 struct evbuffer *buf = evbuffer_new(); 1634 struct evbuffer_ptr ptr1, ptr2; 1635 const char *s; 1636 size_t eol_len; 1637 1638 s = "string! \r\n\r\nx\n"; 1639 evbuffer_add(buf, s, strlen(s)); 1640 eol_len = -1; 1641 ptr1 = evbuffer_search_eol(buf, NULL, &eol_len, EVBUFFER_EOL_CRLF); 1642 tt_int_op(ptr1.pos, ==, 8); 1643 tt_int_op(eol_len, ==, 2); 1644 1645 eol_len = -1; 1646 ptr2 = evbuffer_search_eol(buf, &ptr1, &eol_len, EVBUFFER_EOL_CRLF); 1647 tt_int_op(ptr2.pos, ==, 8); 1648 tt_int_op(eol_len, ==, 2); 1649 1650 evbuffer_ptr_set(buf, &ptr1, 1, EVBUFFER_PTR_ADD); 1651 eol_len = -1; 1652 ptr2 = evbuffer_search_eol(buf, &ptr1, &eol_len, EVBUFFER_EOL_CRLF); 1653 tt_int_op(ptr2.pos, ==, 9); 1654 tt_int_op(eol_len, ==, 1); 1655 1656 eol_len = -1; 1657 ptr2 = evbuffer_search_eol(buf, &ptr1, &eol_len, EVBUFFER_EOL_CRLF_STRICT); 1658 tt_int_op(ptr2.pos, ==, 10); 1659 tt_int_op(eol_len, ==, 2); 1660 1661 eol_len = -1; 1662 ptr1 = evbuffer_search_eol(buf, NULL, &eol_len, EVBUFFER_EOL_LF); 1663 tt_int_op(ptr1.pos, ==, 9); 1664 tt_int_op(eol_len, ==, 1); 1665 1666 eol_len = -1; 1667 ptr2 = evbuffer_search_eol(buf, &ptr1, &eol_len, EVBUFFER_EOL_LF); 1668 tt_int_op(ptr2.pos, ==, 9); 1669 tt_int_op(eol_len, ==, 1); 1670 1671 evbuffer_ptr_set(buf, &ptr1, 1, EVBUFFER_PTR_ADD); 1672 eol_len = -1; 1673 ptr2 = evbuffer_search_eol(buf, &ptr1, &eol_len, EVBUFFER_EOL_LF); 1674 tt_int_op(ptr2.pos, ==, 11); 1675 tt_int_op(eol_len, ==, 1); 1676 1677 tt_assert(evbuffer_ptr_set(buf, &ptr1, evbuffer_get_length(buf), EVBUFFER_PTR_SET) == 0); 1678 eol_len = -1; 1679 ptr2 = evbuffer_search_eol(buf, &ptr1, &eol_len, EVBUFFER_EOL_LF); 1680 tt_int_op(ptr2.pos, ==, -1); 1681 tt_int_op(eol_len, ==, 0); 1682 1683 end: 1684 evbuffer_free(buf); 1685 } 1686 1687 static void 1688 test_evbuffer_iterative(void *ptr) 1689 { 1690 struct evbuffer *buf = evbuffer_new(); 1691 const char *abc = "abcdefghijklmnopqrstvuwxyzabcdefghijklmnopqrstvuwxyzabcdefghijklmnopqrstvuwxyzabcdefghijklmnopqrstvuwxyz"; 1692 unsigned i, j, sum, n; 1693 1694 sum = 0; 1695 n = 0; 1696 for (i = 0; i < 1000; ++i) { 1697 for (j = 1; j < strlen(abc); ++j) { 1698 char format[32]; 1699 evutil_snprintf(format, sizeof(format), "%%%u.%us", j, j); 1700 evbuffer_add_printf(buf, format, abc); 1701 1702 /* Only check for rep violations every so often. 1703 Walking over the whole list of chains can get 1704 pretty expensive as it gets long. 1705 */ 1706 if ((n % 337) == 0) 1707 evbuffer_validate(buf); 1708 1709 sum += j; 1710 n++; 1711 } 1712 } 1713 evbuffer_validate(buf); 1714 1715 tt_uint_op(sum, ==, evbuffer_get_length(buf)); 1716 1717 { 1718 size_t a,w,u; 1719 a=w=u=0; 1720 evbuffer_get_waste(buf, &a, &w, &u); 1721 if (0) 1722 printf("Allocated: %u.\nWasted: %u.\nUsed: %u.", 1723 (unsigned)a, (unsigned)w, (unsigned)u); 1724 tt_assert( ((double)w)/a < .125); 1725 } 1726 end: 1727 evbuffer_free(buf); 1728 1729 } 1730 1731 static void 1732 test_evbuffer_find(void *ptr) 1733 { 1734 unsigned char* p; 1735 const char* test1 = "1234567890\r\n"; 1736 const char* test2 = "1234567890\r"; 1737 #define EVBUFFER_INITIAL_LENGTH 256 1738 char test3[EVBUFFER_INITIAL_LENGTH]; 1739 unsigned int i; 1740 struct evbuffer * buf = evbuffer_new(); 1741 1742 tt_assert(buf); 1743 1744 /* make sure evbuffer_find doesn't match past the end of the buffer */ 1745 evbuffer_add(buf, (unsigned char*)test1, strlen(test1)); 1746 evbuffer_validate(buf); 1747 evbuffer_drain(buf, strlen(test1)); 1748 evbuffer_validate(buf); 1749 evbuffer_add(buf, (unsigned char*)test2, strlen(test2)); 1750 evbuffer_validate(buf); 1751 p = evbuffer_find(buf, (unsigned char*)"\r\n", 2); 1752 tt_want(p == NULL); 1753 1754 /* 1755 * drain the buffer and do another find; in r309 this would 1756 * read past the allocated buffer causing a valgrind error. 1757 */ 1758 evbuffer_drain(buf, strlen(test2)); 1759 evbuffer_validate(buf); 1760 for (i = 0; i < EVBUFFER_INITIAL_LENGTH; ++i) 1761 test3[i] = 'a'; 1762 test3[EVBUFFER_INITIAL_LENGTH - 1] = 'x'; 1763 evbuffer_add(buf, (unsigned char *)test3, EVBUFFER_INITIAL_LENGTH); 1764 evbuffer_validate(buf); 1765 p = evbuffer_find(buf, (unsigned char *)"xy", 2); 1766 tt_want(p == NULL); 1767 1768 /* simple test for match at end of allocated buffer */ 1769 p = evbuffer_find(buf, (unsigned char *)"ax", 2); 1770 tt_assert(p != NULL); 1771 tt_want(strncmp((char*)p, "ax", 2) == 0); 1772 1773 end: 1774 if (buf) 1775 evbuffer_free(buf); 1776 } 1777 1778 static void 1779 test_evbuffer_ptr_set(void *ptr) 1780 { 1781 struct evbuffer *buf = evbuffer_new(); 1782 struct evbuffer_ptr pos; 1783 struct evbuffer_iovec v[1]; 1784 1785 tt_assert(buf); 1786 1787 tt_int_op(evbuffer_get_length(buf), ==, 0); 1788 1789 tt_assert(evbuffer_ptr_set(buf, &pos, 0, EVBUFFER_PTR_SET) == 0); 1790 tt_assert(pos.pos == 0); 1791 tt_assert(evbuffer_ptr_set(buf, &pos, 1, EVBUFFER_PTR_ADD) == -1); 1792 tt_assert(pos.pos == -1); 1793 tt_assert(evbuffer_ptr_set(buf, &pos, 1, EVBUFFER_PTR_SET) == -1); 1794 tt_assert(pos.pos == -1); 1795 1796 /* create some chains */ 1797 evbuffer_reserve_space(buf, 5000, v, 1); 1798 v[0].iov_len = 5000; 1799 memset(v[0].iov_base, 1, v[0].iov_len); 1800 evbuffer_commit_space(buf, v, 1); 1801 evbuffer_validate(buf); 1802 1803 evbuffer_reserve_space(buf, 4000, v, 1); 1804 v[0].iov_len = 4000; 1805 memset(v[0].iov_base, 2, v[0].iov_len); 1806 evbuffer_commit_space(buf, v, 1); 1807 1808 evbuffer_reserve_space(buf, 3000, v, 1); 1809 v[0].iov_len = 3000; 1810 memset(v[0].iov_base, 3, v[0].iov_len); 1811 evbuffer_commit_space(buf, v, 1); 1812 evbuffer_validate(buf); 1813 1814 tt_int_op(evbuffer_get_length(buf), ==, 12000); 1815 1816 tt_assert(evbuffer_ptr_set(buf, &pos, 13000, EVBUFFER_PTR_SET) == -1); 1817 tt_assert(pos.pos == -1); 1818 tt_assert(evbuffer_ptr_set(buf, &pos, 0, EVBUFFER_PTR_SET) == 0); 1819 tt_assert(pos.pos == 0); 1820 tt_assert(evbuffer_ptr_set(buf, &pos, 13000, EVBUFFER_PTR_ADD) == -1); 1821 1822 tt_assert(evbuffer_ptr_set(buf, &pos, 0, EVBUFFER_PTR_SET) == 0); 1823 tt_assert(pos.pos == 0); 1824 tt_assert(evbuffer_ptr_set(buf, &pos, 10000, EVBUFFER_PTR_ADD) == 0); 1825 tt_assert(pos.pos == 10000); 1826 tt_assert(evbuffer_ptr_set(buf, &pos, 1000, EVBUFFER_PTR_ADD) == 0); 1827 tt_assert(pos.pos == 11000); 1828 tt_assert(evbuffer_ptr_set(buf, &pos, 1000, EVBUFFER_PTR_ADD) == 0); 1829 tt_assert(pos.pos == 12000); 1830 tt_assert(evbuffer_ptr_set(buf, &pos, 1000, EVBUFFER_PTR_ADD) == -1); 1831 tt_assert(pos.pos == -1); 1832 1833 end: 1834 if (buf) 1835 evbuffer_free(buf); 1836 } 1837 1838 static void 1839 test_evbuffer_search(void *ptr) 1840 { 1841 struct evbuffer *buf = evbuffer_new(); 1842 struct evbuffer *tmp = evbuffer_new(); 1843 struct evbuffer_ptr pos, end; 1844 1845 tt_assert(buf); 1846 tt_assert(tmp); 1847 1848 pos = evbuffer_search(buf, "x", 1, NULL); 1849 tt_int_op(pos.pos, ==, -1); 1850 tt_assert(evbuffer_ptr_set(buf, &pos, 0, EVBUFFER_PTR_SET) == 0); 1851 pos = evbuffer_search(buf, "x", 1, &pos); 1852 tt_int_op(pos.pos, ==, -1); 1853 tt_assert(evbuffer_ptr_set(buf, &pos, 0, EVBUFFER_PTR_SET) == 0); 1854 pos = evbuffer_search_range(buf, "x", 1, &pos, &pos); 1855 tt_int_op(pos.pos, ==, -1); 1856 tt_assert(evbuffer_ptr_set(buf, &pos, 0, EVBUFFER_PTR_SET) == 0); 1857 pos = evbuffer_search_range(buf, "x", 1, &pos, NULL); 1858 tt_int_op(pos.pos, ==, -1); 1859 1860 /* set up our chains */ 1861 evbuffer_add_printf(tmp, "hello"); /* 5 chars */ 1862 evbuffer_add_buffer(buf, tmp); 1863 evbuffer_add_printf(tmp, "foo"); /* 3 chars */ 1864 evbuffer_add_buffer(buf, tmp); 1865 evbuffer_add_printf(tmp, "cat"); /* 3 chars */ 1866 evbuffer_add_buffer(buf, tmp); 1867 evbuffer_add_printf(tmp, "attack"); 1868 evbuffer_add_buffer(buf, tmp); 1869 1870 pos = evbuffer_search(buf, "attack", 6, NULL); 1871 tt_int_op(pos.pos, ==, 11); 1872 pos = evbuffer_search(buf, "attacker", 8, NULL); 1873 tt_int_op(pos.pos, ==, -1); 1874 1875 /* test continuing search */ 1876 pos = evbuffer_search(buf, "oc", 2, NULL); 1877 tt_int_op(pos.pos, ==, 7); 1878 pos = evbuffer_search(buf, "cat", 3, &pos); 1879 tt_int_op(pos.pos, ==, 8); 1880 pos = evbuffer_search(buf, "tacking", 7, &pos); 1881 tt_int_op(pos.pos, ==, -1); 1882 1883 evbuffer_ptr_set(buf, &pos, 5, EVBUFFER_PTR_SET); 1884 pos = evbuffer_search(buf, "foo", 3, &pos); 1885 tt_int_op(pos.pos, ==, 5); 1886 1887 evbuffer_ptr_set(buf, &pos, 2, EVBUFFER_PTR_ADD); 1888 pos = evbuffer_search(buf, "tat", 3, &pos); 1889 tt_int_op(pos.pos, ==, 10); 1890 1891 /* test bounded search. */ 1892 /* Set "end" to the first t in "attack". */ 1893 evbuffer_ptr_set(buf, &end, 12, EVBUFFER_PTR_SET); 1894 pos = evbuffer_search_range(buf, "foo", 3, NULL, &end); 1895 tt_int_op(pos.pos, ==, 5); 1896 pos = evbuffer_search_range(buf, "foocata", 7, NULL, &end); 1897 tt_int_op(pos.pos, ==, 5); 1898 pos = evbuffer_search_range(buf, "foocatat", 8, NULL, &end); 1899 tt_int_op(pos.pos, ==, -1); 1900 pos = evbuffer_search_range(buf, "ack", 3, NULL, &end); 1901 tt_int_op(pos.pos, ==, -1); 1902 1903 /* Set "end" after the last byte in the buffer. */ 1904 tt_assert(evbuffer_ptr_set(buf, &end, 17, EVBUFFER_PTR_SET) == 0); 1905 1906 pos = evbuffer_search_range(buf, "attack", 6, NULL, &end); 1907 tt_int_op(pos.pos, ==, 11); 1908 tt_assert(evbuffer_ptr_set(buf, &pos, 11, EVBUFFER_PTR_SET) == 0); 1909 pos = evbuffer_search_range(buf, "attack", 6, &pos, &end); 1910 tt_int_op(pos.pos, ==, 11); 1911 tt_assert(evbuffer_ptr_set(buf, &pos, 17, EVBUFFER_PTR_SET) == 0); 1912 pos = evbuffer_search_range(buf, "attack", 6, &pos, &end); 1913 tt_int_op(pos.pos, ==, -1); 1914 tt_assert(evbuffer_ptr_set(buf, &pos, 17, EVBUFFER_PTR_SET) == 0); 1915 pos = evbuffer_search_range(buf, "attack", 6, &pos, NULL); 1916 tt_int_op(pos.pos, ==, -1); 1917 1918 end: 1919 if (buf) 1920 evbuffer_free(buf); 1921 if (tmp) 1922 evbuffer_free(tmp); 1923 } 1924 1925 static void 1926 log_change_callback(struct evbuffer *buffer, 1927 const struct evbuffer_cb_info *cbinfo, 1928 void *arg) 1929 { 1930 1931 size_t old_len = cbinfo->orig_size; 1932 size_t new_len = old_len + cbinfo->n_added - cbinfo->n_deleted; 1933 struct evbuffer *out = arg; 1934 evbuffer_add_printf(out, "%lu->%lu; ", (unsigned long)old_len, 1935 (unsigned long)new_len); 1936 } 1937 static void 1938 self_draining_callback(struct evbuffer *evbuffer, size_t old_len, 1939 size_t new_len, void *arg) 1940 { 1941 if (new_len > old_len) 1942 evbuffer_drain(evbuffer, new_len); 1943 } 1944 1945 static void 1946 test_evbuffer_callbacks(void *ptr) 1947 { 1948 struct evbuffer *buf = evbuffer_new(); 1949 struct evbuffer *buf_out1 = evbuffer_new(); 1950 struct evbuffer *buf_out2 = evbuffer_new(); 1951 struct evbuffer_cb_entry *cb1, *cb2; 1952 1953 tt_assert(buf); 1954 tt_assert(buf_out1); 1955 tt_assert(buf_out2); 1956 1957 cb1 = evbuffer_add_cb(buf, log_change_callback, buf_out1); 1958 cb2 = evbuffer_add_cb(buf, log_change_callback, buf_out2); 1959 1960 /* Let's run through adding and deleting some stuff from the buffer 1961 * and turning the callbacks on and off and removing them. The callback 1962 * adds a summary of length changes to buf_out1/buf_out2 when called. */ 1963 /* size: 0-> 36. */ 1964 evbuffer_add_printf(buf, "The %d magic words are spotty pudding", 2); 1965 evbuffer_validate(buf); 1966 evbuffer_cb_clear_flags(buf, cb2, EVBUFFER_CB_ENABLED); 1967 evbuffer_drain(buf, 10); /*36->26*/ 1968 evbuffer_validate(buf); 1969 evbuffer_prepend(buf, "Hello", 5);/*26->31*/ 1970 evbuffer_cb_set_flags(buf, cb2, EVBUFFER_CB_ENABLED); 1971 evbuffer_add_reference(buf, "Goodbye", 7, NULL, NULL); /*31->38*/ 1972 evbuffer_remove_cb_entry(buf, cb1); 1973 evbuffer_validate(buf); 1974 evbuffer_drain(buf, evbuffer_get_length(buf)); /*38->0*/; 1975 tt_assert(-1 == evbuffer_remove_cb(buf, log_change_callback, NULL)); 1976 evbuffer_add(buf, "X", 1); /* 0->1 */ 1977 tt_assert(!evbuffer_remove_cb(buf, log_change_callback, buf_out2)); 1978 evbuffer_validate(buf); 1979 1980 tt_str_op((const char *) evbuffer_pullup(buf_out1, -1), ==, 1981 "0->36; 36->26; 26->31; 31->38; "); 1982 tt_str_op((const char *) evbuffer_pullup(buf_out2, -1), ==, 1983 "0->36; 31->38; 38->0; 0->1; "); 1984 evbuffer_drain(buf_out1, evbuffer_get_length(buf_out1)); 1985 evbuffer_drain(buf_out2, evbuffer_get_length(buf_out2)); 1986 /* Let's test the obsolete buffer_setcb function too. */ 1987 cb1 = evbuffer_add_cb(buf, log_change_callback, buf_out1); 1988 tt_assert(cb1 != NULL); 1989 cb2 = evbuffer_add_cb(buf, log_change_callback, buf_out2); 1990 tt_assert(cb2 != NULL); 1991 tt_int_op(evbuffer_setcb(buf, self_draining_callback, NULL), ==, 0); 1992 evbuffer_add_printf(buf, "This should get drained right away."); 1993 tt_uint_op(evbuffer_get_length(buf), ==, 0); 1994 tt_uint_op(evbuffer_get_length(buf_out1), ==, 0); 1995 tt_uint_op(evbuffer_get_length(buf_out2), ==, 0); 1996 tt_int_op(evbuffer_setcb(buf, NULL, NULL), ==, 0); 1997 evbuffer_add_printf(buf, "This will not."); 1998 tt_str_op((const char *) evbuffer_pullup(buf, -1), ==, "This will not."); 1999 evbuffer_validate(buf); 2000 evbuffer_drain(buf, evbuffer_get_length(buf)); 2001 evbuffer_validate(buf); 2002 #if 0 2003 /* Now let's try a suspended callback. */ 2004 cb1 = evbuffer_add_cb(buf, log_change_callback, buf_out1); 2005 cb2 = evbuffer_add_cb(buf, log_change_callback, buf_out2); 2006 evbuffer_cb_suspend(buf,cb2); 2007 evbuffer_prepend(buf,"Hello world",11); /*0->11*/ 2008 evbuffer_validate(buf); 2009 evbuffer_cb_suspend(buf,cb1); 2010 evbuffer_add(buf,"more",4); /* 11->15 */ 2011 evbuffer_cb_unsuspend(buf,cb2); 2012 evbuffer_drain(buf, 4); /* 15->11 */ 2013 evbuffer_cb_unsuspend(buf,cb1); 2014 evbuffer_drain(buf, evbuffer_get_length(buf)); /* 11->0 */ 2015 2016 tt_str_op(evbuffer_pullup(buf_out1, -1), ==, 2017 "0->11; 11->11; 11->0; "); 2018 tt_str_op(evbuffer_pullup(buf_out2, -1), ==, 2019 "0->15; 15->11; 11->0; "); 2020 #endif 2021 2022 /* the next call to readline should fail */ 2023 #ifndef EVENT__DISABLE_MM_REPLACEMENT 2024 event_set_mem_functions(failing_malloc, realloc, free); 2025 tt_int_op(evbuffer_setcb(buf, self_draining_callback, NULL), ==, -1); 2026 evbuffer_validate(buf); 2027 event_set_mem_functions(malloc, realloc, free); 2028 #endif 2029 2030 end: 2031 if (buf) 2032 evbuffer_free(buf); 2033 if (buf_out1) 2034 evbuffer_free(buf_out1); 2035 if (buf_out2) 2036 evbuffer_free(buf_out2); 2037 } 2038 2039 static int ref_done_cb_called_count = 0; 2040 static void *ref_done_cb_called_with = NULL; 2041 static const void *ref_done_cb_called_with_data = NULL; 2042 static size_t ref_done_cb_called_with_len = 0; 2043 static void ref_done_cb(const void *data, size_t len, void *info) 2044 { 2045 ++ref_done_cb_called_count; 2046 ref_done_cb_called_with = info; 2047 ref_done_cb_called_with_data = data; 2048 ref_done_cb_called_with_len = len; 2049 } 2050 2051 static void 2052 test_evbuffer_add_reference(void *ptr) 2053 { 2054 const char chunk1[] = "If you have found the answer to such a problem"; 2055 const char chunk2[] = "you ought to write it up for publication"; 2056 /* -- Knuth's "Notes on the Exercises" from TAOCP */ 2057 char tmp[16]; 2058 size_t len1 = strlen(chunk1), len2=strlen(chunk2); 2059 2060 struct evbuffer *buf1 = NULL, *buf2 = NULL; 2061 2062 buf1 = evbuffer_new(); 2063 tt_assert(buf1); 2064 2065 evbuffer_add_reference(buf1, chunk1, len1, ref_done_cb, (void*)111); 2066 evbuffer_add(buf1, ", ", 2); 2067 evbuffer_add_reference(buf1, chunk2, len2, ref_done_cb, (void*)222); 2068 tt_int_op(evbuffer_get_length(buf1), ==, len1+len2+2); 2069 2070 /* Make sure we can drain a little from a reference. */ 2071 tt_int_op(evbuffer_remove(buf1, tmp, 6), ==, 6); 2072 tt_int_op(memcmp(tmp, "If you", 6), ==, 0); 2073 tt_int_op(evbuffer_remove(buf1, tmp, 5), ==, 5); 2074 tt_int_op(memcmp(tmp, " have", 5), ==, 0); 2075 2076 /* Make sure that prepending does not meddle with immutable data */ 2077 tt_int_op(evbuffer_prepend(buf1, "I have ", 7), ==, 0); 2078 tt_int_op(memcmp(chunk1, "If you", 6), ==, 0); 2079 evbuffer_validate(buf1); 2080 2081 /* Make sure that when the chunk is over, the callback is invoked. */ 2082 evbuffer_drain(buf1, 7); /* Remove prepended stuff. */ 2083 evbuffer_drain(buf1, len1-11-1); /* remove all but one byte of chunk1 */ 2084 tt_int_op(ref_done_cb_called_count, ==, 0); 2085 evbuffer_remove(buf1, tmp, 1); 2086 tt_int_op(tmp[0], ==, 'm'); 2087 tt_assert(ref_done_cb_called_with == (void*)111); 2088 tt_assert(ref_done_cb_called_with_data == chunk1); 2089 tt_assert(ref_done_cb_called_with_len == len1); 2090 tt_int_op(ref_done_cb_called_count, ==, 1); 2091 evbuffer_validate(buf1); 2092 2093 /* Drain some of the remaining chunk, then add it to another buffer */ 2094 evbuffer_drain(buf1, 6); /* Remove the ", you ". */ 2095 buf2 = evbuffer_new(); 2096 tt_assert(buf2); 2097 tt_int_op(ref_done_cb_called_count, ==, 1); 2098 evbuffer_add(buf2, "I ", 2); 2099 2100 evbuffer_add_buffer(buf2, buf1); 2101 tt_int_op(ref_done_cb_called_count, ==, 1); 2102 evbuffer_remove(buf2, tmp, 16); 2103 tt_int_op(memcmp("I ought to write", tmp, 16), ==, 0); 2104 evbuffer_drain(buf2, evbuffer_get_length(buf2)); 2105 tt_int_op(ref_done_cb_called_count, ==, 2); 2106 tt_assert(ref_done_cb_called_with == (void*)222); 2107 evbuffer_validate(buf2); 2108 2109 /* Now add more stuff to buf1 and make sure that it gets removed on 2110 * free. */ 2111 evbuffer_add(buf1, "You shake and shake the ", 24); 2112 evbuffer_add_reference(buf1, "ketchup bottle", 14, ref_done_cb, 2113 (void*)3333); 2114 evbuffer_add(buf1, ". Nothing comes and then a lot'll.", 35); 2115 evbuffer_free(buf1); 2116 buf1 = NULL; 2117 tt_int_op(ref_done_cb_called_count, ==, 3); 2118 tt_assert(ref_done_cb_called_with == (void*)3333); 2119 2120 end: 2121 if (buf1) 2122 evbuffer_free(buf1); 2123 if (buf2) 2124 evbuffer_free(buf2); 2125 } 2126 2127 static void 2128 test_evbuffer_multicast(void *ptr) 2129 { 2130 const char chunk1[] = "If you have found the answer to such a problem"; 2131 const char chunk2[] = "you ought to write it up for publication"; 2132 /* -- Knuth's "Notes on the Exercises" from TAOCP */ 2133 char tmp[16]; 2134 size_t len1 = strlen(chunk1), len2=strlen(chunk2); 2135 2136 struct evbuffer *buf1 = NULL, *buf2 = NULL; 2137 2138 buf1 = evbuffer_new(); 2139 tt_assert(buf1); 2140 2141 evbuffer_add(buf1, chunk1, len1); 2142 evbuffer_add(buf1, ", ", 2); 2143 evbuffer_add(buf1, chunk2, len2); 2144 tt_int_op(evbuffer_get_length(buf1), ==, len1+len2+2); 2145 2146 buf2 = evbuffer_new(); 2147 tt_assert(buf2); 2148 2149 tt_int_op(evbuffer_add_buffer_reference(buf2, buf1), ==, 0); 2150 /* nested references are not allowed */ 2151 tt_int_op(evbuffer_add_buffer_reference(buf2, buf2), ==, -1); 2152 tt_int_op(evbuffer_add_buffer_reference(buf1, buf2), ==, -1); 2153 2154 /* both buffers contain the same amount of data */ 2155 tt_int_op(evbuffer_get_length(buf1), ==, evbuffer_get_length(buf1)); 2156 2157 /* Make sure we can drain a little from the first buffer. */ 2158 tt_int_op(evbuffer_remove(buf1, tmp, 6), ==, 6); 2159 tt_int_op(memcmp(tmp, "If you", 6), ==, 0); 2160 tt_int_op(evbuffer_remove(buf1, tmp, 5), ==, 5); 2161 tt_int_op(memcmp(tmp, " have", 5), ==, 0); 2162 2163 /* Make sure that prepending does not meddle with immutable data */ 2164 tt_int_op(evbuffer_prepend(buf1, "I have ", 7), ==, 0); 2165 tt_int_op(memcmp(chunk1, "If you", 6), ==, 0); 2166 evbuffer_validate(buf1); 2167 2168 /* Make sure we can drain a little from the second buffer. */ 2169 tt_int_op(evbuffer_remove(buf2, tmp, 6), ==, 6); 2170 tt_int_op(memcmp(tmp, "If you", 6), ==, 0); 2171 tt_int_op(evbuffer_remove(buf2, tmp, 5), ==, 5); 2172 tt_int_op(memcmp(tmp, " have", 5), ==, 0); 2173 2174 /* Make sure that prepending does not meddle with immutable data */ 2175 tt_int_op(evbuffer_prepend(buf2, "I have ", 7), ==, 0); 2176 tt_int_op(memcmp(chunk1, "If you", 6), ==, 0); 2177 evbuffer_validate(buf2); 2178 2179 /* Make sure the data can be read from the second buffer when the first is freed */ 2180 evbuffer_free(buf1); 2181 buf1 = NULL; 2182 2183 tt_int_op(evbuffer_remove(buf2, tmp, 6), ==, 6); 2184 tt_int_op(memcmp(tmp, "I have", 6), ==, 0); 2185 2186 tt_int_op(evbuffer_remove(buf2, tmp, 6), ==, 6); 2187 tt_int_op(memcmp(tmp, " foun", 6), ==, 0); 2188 2189 end: 2190 if (buf1) 2191 evbuffer_free(buf1); 2192 if (buf2) 2193 evbuffer_free(buf2); 2194 } 2195 2196 static void 2197 test_evbuffer_multicast_drain(void *ptr) 2198 { 2199 const char chunk1[] = "If you have found the answer to such a problem"; 2200 const char chunk2[] = "you ought to write it up for publication"; 2201 /* -- Knuth's "Notes on the Exercises" from TAOCP */ 2202 size_t len1 = strlen(chunk1), len2=strlen(chunk2); 2203 2204 struct evbuffer *buf1 = NULL, *buf2 = NULL; 2205 2206 buf1 = evbuffer_new(); 2207 tt_assert(buf1); 2208 2209 evbuffer_add(buf1, chunk1, len1); 2210 evbuffer_add(buf1, ", ", 2); 2211 evbuffer_add(buf1, chunk2, len2); 2212 tt_int_op(evbuffer_get_length(buf1), ==, len1+len2+2); 2213 2214 buf2 = evbuffer_new(); 2215 tt_assert(buf2); 2216 2217 tt_int_op(evbuffer_add_buffer_reference(buf2, buf1), ==, 0); 2218 tt_int_op(evbuffer_get_length(buf2), ==, len1+len2+2); 2219 tt_int_op(evbuffer_drain(buf1, evbuffer_get_length(buf1)), ==, 0); 2220 tt_int_op(evbuffer_get_length(buf2), ==, len1+len2+2); 2221 tt_int_op(evbuffer_drain(buf2, evbuffer_get_length(buf2)), ==, 0); 2222 evbuffer_validate(buf1); 2223 evbuffer_validate(buf2); 2224 2225 end: 2226 if (buf1) 2227 evbuffer_free(buf1); 2228 if (buf2) 2229 evbuffer_free(buf2); 2230 } 2231 2232 static void 2233 check_prepend(struct evbuffer *buffer, 2234 const struct evbuffer_cb_info *cbinfo, 2235 void *arg) 2236 { 2237 tt_int_op(cbinfo->orig_size, ==, 3); 2238 tt_int_op(cbinfo->n_added, ==, 8096); 2239 tt_int_op(cbinfo->n_deleted, ==, 0); 2240 end: 2241 ; 2242 } 2243 /* Some cases that we didn't get in test_evbuffer() above, for more coverage. */ 2244 static void 2245 test_evbuffer_prepend(void *ptr) 2246 { 2247 struct evbuffer *buf1 = NULL, *buf2 = NULL; 2248 char tmp[128], *buffer = malloc(8096); 2249 int n; 2250 2251 buf1 = evbuffer_new(); 2252 tt_assert(buf1); 2253 2254 /* Case 0: The evbuffer is entirely empty. */ 2255 evbuffer_prepend(buf1, "This string has 29 characters", 29); 2256 evbuffer_validate(buf1); 2257 2258 /* Case 1: Prepend goes entirely in new chunk. */ 2259 evbuffer_prepend(buf1, "Short.", 6); 2260 evbuffer_validate(buf1); 2261 2262 /* Case 2: prepend goes entirely in first chunk. */ 2263 evbuffer_drain(buf1, 6+11); 2264 evbuffer_prepend(buf1, "it", 2); 2265 evbuffer_validate(buf1); 2266 tt_assert(!memcmp(buf1->first->buffer+buf1->first->misalign, 2267 "it has", 6)); 2268 2269 /* Case 3: prepend is split over multiple chunks. */ 2270 evbuffer_prepend(buf1, "It is no longer true to say ", 28); 2271 evbuffer_validate(buf1); 2272 n = evbuffer_remove(buf1, tmp, sizeof(tmp)-1); 2273 tt_int_op(n, >=, 0); 2274 tmp[n]='\0'; 2275 tt_str_op(tmp,==,"It is no longer true to say it has 29 characters"); 2276 2277 buf2 = evbuffer_new(); 2278 tt_assert(buf2); 2279 2280 /* Case 4: prepend a buffer to an empty buffer. */ 2281 n = 999; 2282 evbuffer_add_printf(buf1, "Here is string %d. ", n++); 2283 evbuffer_prepend_buffer(buf2, buf1); 2284 evbuffer_validate(buf2); 2285 2286 /* Case 5: prepend a buffer to a nonempty buffer. */ 2287 evbuffer_add_printf(buf1, "Here is string %d. ", n++); 2288 evbuffer_prepend_buffer(buf2, buf1); 2289 evbuffer_validate(buf2); 2290 evbuffer_validate(buf1); 2291 n = evbuffer_remove(buf2, tmp, sizeof(tmp)-1); 2292 tt_int_op(n, >=, 0); 2293 tmp[n]='\0'; 2294 tt_str_op(tmp,==,"Here is string 1000. Here is string 999. "); 2295 2296 /* Case 5: evbuffer_prepend() will need a new buffer, with callbacks */ 2297 memset(buffer, 'A', 8096); 2298 evbuffer_free(buf2); 2299 buf2 = evbuffer_new(); 2300 tt_assert(buf2); 2301 evbuffer_prepend(buf2, "foo", 3); 2302 evbuffer_add_cb(buf2, check_prepend, NULL); 2303 evbuffer_prepend(buf2, buffer, 8096); 2304 evbuffer_remove_cb(buf2, check_prepend, NULL); 2305 evbuffer_validate(buf2); 2306 tt_nstr_op(8096,(char *)evbuffer_pullup(buf2, 8096),==,buffer); 2307 evbuffer_drain(buf2, 8096); 2308 tt_nstr_op(3,(char *)evbuffer_pullup(buf2, 3),==,"foo"); 2309 evbuffer_drain(buf2, 3); 2310 2311 end: 2312 free(buffer); 2313 if (buf1) 2314 evbuffer_free(buf1); 2315 if (buf2) 2316 evbuffer_free(buf2); 2317 2318 } 2319 2320 static void 2321 test_evbuffer_empty_reference_prepend(void *ptr) 2322 { 2323 struct evbuffer *buf = NULL; 2324 2325 buf = evbuffer_new(); 2326 tt_assert(buf); 2327 2328 /** empty chain could leave invalid last_with_datap */ 2329 evbuffer_add_reference(buf, "", 0, NULL, NULL); 2330 evbuffer_validate(buf); 2331 evbuffer_prepend(buf, "foo", 3); 2332 2333 evbuffer_validate(buf); 2334 tt_assert(!strncmp((char *)evbuffer_pullup(buf, -1), "foo", 3)); 2335 evbuffer_validate(buf); 2336 2337 end: 2338 if (buf) 2339 evbuffer_free(buf); 2340 } 2341 static void 2342 test_evbuffer_empty_reference_prepend_buffer(void *ptr) 2343 { 2344 struct evbuffer *buf1 = NULL, *buf2 = NULL; 2345 2346 buf1 = evbuffer_new(); 2347 tt_assert(buf1); 2348 buf2 = evbuffer_new(); 2349 tt_assert(buf2); 2350 2351 /** empty chain could leave invalid last_with_datap */ 2352 evbuffer_add_reference(buf1, "", 0, NULL, NULL); 2353 evbuffer_validate(buf1); 2354 evbuffer_add(buf2, "foo", 3); 2355 evbuffer_validate(buf2); 2356 evbuffer_prepend_buffer(buf2, buf1); 2357 evbuffer_validate(buf2); 2358 2359 tt_assert(!strncmp((char *)evbuffer_pullup(buf2, -1), "foo", 3)); 2360 evbuffer_validate(buf2); 2361 2362 tt_assert(evbuffer_pullup(buf1, -1) == NULL); 2363 evbuffer_validate(buf2); 2364 2365 end: 2366 if (buf1) 2367 evbuffer_free(buf1); 2368 if (buf2) 2369 evbuffer_free(buf2); 2370 } 2371 2372 static void 2373 test_evbuffer_peek_first_gt(void *info) 2374 { 2375 struct evbuffer *buf = NULL, *tmp_buf = NULL; 2376 struct evbuffer_ptr ptr; 2377 struct evbuffer_iovec v[2]; 2378 2379 buf = evbuffer_new(); 2380 tmp_buf = evbuffer_new(); 2381 evbuffer_add_printf(tmp_buf, "Contents of chunk 100\n"); 2382 evbuffer_add_buffer(buf, tmp_buf); 2383 evbuffer_add_printf(tmp_buf, "Contents of chunk 1\n"); 2384 evbuffer_add_buffer(buf, tmp_buf); 2385 2386 evbuffer_ptr_set(buf, &ptr, 0, EVBUFFER_PTR_SET); 2387 2388 /** The only case that matters*/ 2389 tt_int_op(evbuffer_peek(buf, -1, &ptr, NULL, 0), ==, 2); 2390 /** Just in case */ 2391 tt_int_op(evbuffer_peek(buf, -1, &ptr, v, 2), ==, 2); 2392 2393 evbuffer_ptr_set(buf, &ptr, 20, EVBUFFER_PTR_ADD); 2394 tt_int_op(evbuffer_peek(buf, -1, &ptr, NULL, 0), ==, 2); 2395 tt_int_op(evbuffer_peek(buf, -1, &ptr, v, 2), ==, 2); 2396 tt_int_op(evbuffer_peek(buf, 2, &ptr, NULL, 0), ==, 1); 2397 tt_int_op(evbuffer_peek(buf, 2, &ptr, v, 2), ==, 1); 2398 tt_int_op(evbuffer_peek(buf, 3, &ptr, NULL, 0), ==, 2); 2399 tt_int_op(evbuffer_peek(buf, 3, &ptr, v, 2), ==, 2); 2400 2401 end: 2402 if (buf) 2403 evbuffer_free(buf); 2404 if (tmp_buf) 2405 evbuffer_free(tmp_buf); 2406 } 2407 2408 static void 2409 test_evbuffer_peek(void *info) 2410 { 2411 struct evbuffer *buf = NULL, *tmp_buf = NULL; 2412 int i; 2413 struct evbuffer_iovec v[20]; 2414 struct evbuffer_ptr ptr; 2415 2416 #define tt_iov_eq(v, s) \ 2417 tt_int_op((v)->iov_len, ==, strlen(s)); \ 2418 tt_assert(!memcmp((v)->iov_base, (s), strlen(s))) 2419 2420 /* Let's make a very fragmented buffer. */ 2421 buf = evbuffer_new(); 2422 tmp_buf = evbuffer_new(); 2423 for (i = 0; i < 16; ++i) { 2424 evbuffer_add_printf(tmp_buf, "Contents of chunk [%d]\n", i); 2425 evbuffer_add_buffer(buf, tmp_buf); 2426 } 2427 2428 /* How many chunks do we need for everything? */ 2429 i = evbuffer_peek(buf, -1, NULL, NULL, 0); 2430 tt_int_op(i, ==, 16); 2431 2432 /* Simple peek: get everything. */ 2433 i = evbuffer_peek(buf, -1, NULL, v, 20); 2434 tt_int_op(i, ==, 16); /* we used only 16 chunks. */ 2435 tt_iov_eq(&v[0], "Contents of chunk [0]\n"); 2436 tt_iov_eq(&v[3], "Contents of chunk [3]\n"); 2437 tt_iov_eq(&v[12], "Contents of chunk [12]\n"); 2438 tt_iov_eq(&v[15], "Contents of chunk [15]\n"); 2439 2440 /* Just get one chunk worth. */ 2441 memset(v, 0, sizeof(v)); 2442 i = evbuffer_peek(buf, -1, NULL, v, 1); 2443 tt_int_op(i, ==, 1); 2444 tt_iov_eq(&v[0], "Contents of chunk [0]\n"); 2445 tt_assert(v[1].iov_base == NULL); 2446 2447 /* Suppose we want at least the first 40 bytes. */ 2448 memset(v, 0, sizeof(v)); 2449 i = evbuffer_peek(buf, 40, NULL, v, 16); 2450 tt_int_op(i, ==, 2); 2451 tt_iov_eq(&v[0], "Contents of chunk [0]\n"); 2452 tt_iov_eq(&v[1], "Contents of chunk [1]\n"); 2453 tt_assert(v[2].iov_base == NULL); 2454 2455 /* How many chunks do we need for 100 bytes? */ 2456 memset(v, 0, sizeof(v)); 2457 i = evbuffer_peek(buf, 100, NULL, NULL, 0); 2458 tt_int_op(i, ==, 5); 2459 tt_assert(v[0].iov_base == NULL); 2460 2461 /* Now we ask for more bytes than we provide chunks for */ 2462 memset(v, 0, sizeof(v)); 2463 i = evbuffer_peek(buf, 60, NULL, v, 1); 2464 tt_int_op(i, ==, 3); 2465 tt_iov_eq(&v[0], "Contents of chunk [0]\n"); 2466 tt_assert(v[1].iov_base == NULL); 2467 2468 /* Now we ask for more bytes than the buffer has. */ 2469 memset(v, 0, sizeof(v)); 2470 i = evbuffer_peek(buf, 65536, NULL, v, 20); 2471 tt_int_op(i, ==, 16); /* we used only 16 chunks. */ 2472 tt_iov_eq(&v[0], "Contents of chunk [0]\n"); 2473 tt_iov_eq(&v[3], "Contents of chunk [3]\n"); 2474 tt_iov_eq(&v[12], "Contents of chunk [12]\n"); 2475 tt_iov_eq(&v[15], "Contents of chunk [15]\n"); 2476 tt_assert(v[16].iov_base == NULL); 2477 2478 /* What happens if we try an empty buffer? */ 2479 memset(v, 0, sizeof(v)); 2480 i = evbuffer_peek(tmp_buf, -1, NULL, v, 20); 2481 tt_int_op(i, ==, 0); 2482 tt_assert(v[0].iov_base == NULL); 2483 memset(v, 0, sizeof(v)); 2484 i = evbuffer_peek(tmp_buf, 50, NULL, v, 20); 2485 tt_int_op(i, ==, 0); 2486 tt_assert(v[0].iov_base == NULL); 2487 2488 /* Okay, now time to have fun with pointers. */ 2489 memset(v, 0, sizeof(v)); 2490 evbuffer_ptr_set(buf, &ptr, 30, EVBUFFER_PTR_SET); 2491 i = evbuffer_peek(buf, 50, &ptr, v, 20); 2492 tt_int_op(i, ==, 3); 2493 tt_iov_eq(&v[0], " of chunk [1]\n"); 2494 tt_iov_eq(&v[1], "Contents of chunk [2]\n"); 2495 tt_iov_eq(&v[2], "Contents of chunk [3]\n"); /*more than we asked for*/ 2496 2497 /* advance to the start of another chain. */ 2498 memset(v, 0, sizeof(v)); 2499 evbuffer_ptr_set(buf, &ptr, 14, EVBUFFER_PTR_ADD); 2500 i = evbuffer_peek(buf, 44, &ptr, v, 20); 2501 tt_int_op(i, ==, 2); 2502 tt_iov_eq(&v[0], "Contents of chunk [2]\n"); 2503 tt_iov_eq(&v[1], "Contents of chunk [3]\n"); /*more than we asked for*/ 2504 2505 /* peek at the end of the buffer */ 2506 memset(v, 0, sizeof(v)); 2507 tt_assert(evbuffer_ptr_set(buf, &ptr, evbuffer_get_length(buf), EVBUFFER_PTR_SET) == 0); 2508 i = evbuffer_peek(buf, 44, &ptr, v, 20); 2509 tt_int_op(i, ==, 0); 2510 tt_assert(v[0].iov_base == NULL); 2511 2512 end: 2513 if (buf) 2514 evbuffer_free(buf); 2515 if (tmp_buf) 2516 evbuffer_free(tmp_buf); 2517 } 2518 2519 /* Check whether evbuffer freezing works right. This is called twice, 2520 once with the argument "start" and once with the argument "end". 2521 When we test "start", we freeze the start of an evbuffer and make sure 2522 that modifying the start of the buffer doesn't work. When we test 2523 "end", we freeze the end of an evbuffer and make sure that modifying 2524 the end of the buffer doesn't work. 2525 */ 2526 static void 2527 test_evbuffer_freeze(void *ptr) 2528 { 2529 struct basic_test_data *testdata = ptr; 2530 evutil_socket_t *pair = testdata->pair; 2531 struct evbuffer *buf = NULL, *buf_two = NULL, *tmp_buf = NULL; 2532 const char string[] = /* Year's End, Richard Wilbur */ 2533 "I've known the wind by water banks to shake\n" 2534 "The late leaves down, which frozen where they fell\n" 2535 "And held in ice as dancers in a spell\n" 2536 "Fluttered all winter long into a lake..."; 2537 const int start = !strcmp(testdata->setup_data, "start"); 2538 const char tmpfilecontent[] = "file_freeze_test_file"; 2539 char *cp; 2540 char charbuf[128]; 2541 char *tmpfilename = NULL; 2542 int fd = -1; 2543 int r; 2544 size_t orig_length, len; 2545 struct evbuffer_iovec v[1]; 2546 2547 if (!start) 2548 tt_str_op(testdata->setup_data, ==, "end"); 2549 2550 buf = evbuffer_new(); 2551 buf_two = evbuffer_new(); 2552 tmp_buf = evbuffer_new(); 2553 tt_assert(tmp_buf); 2554 2555 evbuffer_add(buf, string, strlen(string)); 2556 evbuffer_add(buf_two, "abc", 3); 2557 evbuffer_add(tmp_buf, "xyz", 3); 2558 evbuffer_freeze(buf, start); /* Freeze the start or the end.*/ 2559 evbuffer_freeze(buf_two, start); 2560 2561 #define FREEZE_EQ(a, startcase, endcase) \ 2562 do { \ 2563 if (start) { \ 2564 tt_int_op((a), ==, (startcase)); \ 2565 } else { \ 2566 tt_int_op((a), ==, (endcase)); \ 2567 } \ 2568 } while (0) 2569 2570 2571 orig_length = evbuffer_get_length(buf); 2572 2573 /* These functions all manipulate the end of buf. */ 2574 r = evbuffer_add(buf, "abc", 0); 2575 FREEZE_EQ(r, 0, -1); 2576 r = evbuffer_reserve_space(buf, 10, v, 1); 2577 FREEZE_EQ(r, 1, -1); 2578 if (r == 1) { 2579 memset(v[0].iov_base, 'X', 10); 2580 v[0].iov_len = 10; 2581 } 2582 r = evbuffer_commit_space(buf, v, 1); 2583 FREEZE_EQ(r, 0, -1); 2584 r = evbuffer_add_reference(buf, string, 5, NULL, NULL); 2585 FREEZE_EQ(r, 0, -1); 2586 r = evbuffer_add_printf(buf, "Hello %s", "world"); 2587 FREEZE_EQ(r, 11, -1); 2588 2589 r = evbuffer_add_buffer(buf, tmp_buf); 2590 FREEZE_EQ(r, 0, -1); 2591 len = strlen(tmpfilecontent); 2592 fd = regress_make_tmpfile(tmpfilecontent, len, &tmpfilename); 2593 r = evbuffer_add_file(buf, fd, 0, len); 2594 FREEZE_EQ(r, 0, -1); 2595 2596 if (start) 2597 evbuffer_add(tmp_buf, "xyz", 3); 2598 2599 tt_assert(evbuffer_get_length(tmp_buf)); 2600 len = evbuffer_get_length(tmp_buf); 2601 evbuffer_write(tmp_buf, pair[0]); 2602 r = evbuffer_read(buf, pair[1], -1); 2603 FREEZE_EQ(r, len, -1); 2604 2605 if (!start) 2606 tt_int_op(orig_length, ==, evbuffer_get_length(buf)); 2607 2608 orig_length = evbuffer_get_length(buf); 2609 2610 /* These functions all manipulate the start of buf. */ 2611 r = evbuffer_remove(buf, charbuf, 1); 2612 FREEZE_EQ(r, -1, 1); 2613 r = evbuffer_drain(buf, 3); 2614 FREEZE_EQ(r, -1, 0); 2615 r = evbuffer_prepend(buf, "dummy", 5); 2616 FREEZE_EQ(r, -1, 0); 2617 cp = evbuffer_readln(buf, NULL, EVBUFFER_EOL_LF); 2618 FREEZE_EQ(cp==NULL, 1, 0); 2619 if (cp) 2620 free(cp); 2621 2622 evbuffer_add(tmp_buf, "xyz", 3); 2623 tt_assert(evbuffer_get_length(tmp_buf)); 2624 r = evbuffer_remove_buffer(buf, tmp_buf, 3); 2625 FREEZE_EQ(r, -1, 3); 2626 r = evbuffer_drain(buf, 3); 2627 FREEZE_EQ(r, -1, 0); 2628 r = evbuffer_prepend_buffer(buf, tmp_buf); 2629 FREEZE_EQ(r, -1, 0); 2630 2631 len = evbuffer_get_length(buf); 2632 r = evbuffer_write(buf, pair[0]); 2633 evbuffer_read(tmp_buf, pair[1], -1); 2634 FREEZE_EQ(r, -1, len); 2635 len = evbuffer_get_length(buf_two); 2636 r = evbuffer_write_atmost(buf_two, pair[0], -1); 2637 evbuffer_read(tmp_buf, pair[1], -1); 2638 FREEZE_EQ(r, -1, len); 2639 2640 if (start) 2641 tt_int_op(orig_length, ==, evbuffer_get_length(buf)); 2642 2643 end: 2644 if (buf) 2645 evbuffer_free(buf); 2646 2647 if (buf_two) 2648 evbuffer_free(buf_two); 2649 2650 if (tmp_buf) 2651 evbuffer_free(tmp_buf); 2652 2653 if (tmpfilename) { 2654 unlink(tmpfilename); 2655 free(tmpfilename); 2656 } 2657 } 2658 2659 static void 2660 test_evbuffer_add_iovec(void * ptr) 2661 { 2662 struct evbuffer * buf = NULL; 2663 struct evbuffer_iovec vec[4]; 2664 const char * data[] = { 2665 "Guilt resembles a sword with two edges.", 2666 "On the one hand, it cuts for Justice, imposing practical morality upon those who fear it.", 2667 "Conscience does not always adhere to rational judgment.", 2668 "Guilt is always a self-imposed burden, but it is not always rightly imposed." 2669 /* -- R.A. Salvatore, _Sojurn_ */ 2670 }; 2671 size_t expected_length = 0; 2672 size_t returned_length = 0; 2673 int i; 2674 2675 buf = evbuffer_new(); 2676 2677 tt_assert(buf); 2678 2679 for (i = 0; i < 4; i++) { 2680 vec[i].iov_len = strlen(data[i]); 2681 vec[i].iov_base = (char*) data[i]; 2682 expected_length += vec[i].iov_len; 2683 } 2684 2685 returned_length = evbuffer_add_iovec(buf, vec, 4); 2686 2687 tt_int_op(returned_length, ==, evbuffer_get_length(buf)); 2688 tt_int_op(evbuffer_get_length(buf), ==, expected_length); 2689 2690 for (i = 0; i < 4; i++) { 2691 char charbuf[1024]; 2692 2693 memset(charbuf, 0, 1024); 2694 evbuffer_remove(buf, charbuf, strlen(data[i])); 2695 tt_assert(strcmp(charbuf, data[i]) == 0); 2696 } 2697 2698 tt_assert(evbuffer_get_length(buf) == 0); 2699 end: 2700 if (buf) { 2701 evbuffer_free(buf); 2702 } 2703 } 2704 2705 static void 2706 test_evbuffer_copyout(void *dummy) 2707 { 2708 const char string[] = 2709 "Still they skirmish to and fro, men my messmates on the snow " 2710 "When we headed off the aurochs turn for turn; " 2711 "When the rich Allobrogenses never kept amanuenses, " 2712 "And our only plots were piled in lakes at Berne."; 2713 /* -- Kipling, "In The Neolithic Age" */ 2714 char tmp[1024]; 2715 struct evbuffer_ptr ptr; 2716 struct evbuffer *buf; 2717 2718 (void)dummy; 2719 2720 buf = evbuffer_new(); 2721 tt_assert(buf); 2722 2723 tt_int_op(strlen(string), ==, 206); 2724 2725 /* Ensure separate chains */ 2726 evbuffer_add_reference(buf, string, 80, no_cleanup, NULL); 2727 evbuffer_add_reference(buf, string+80, 80, no_cleanup, NULL); 2728 evbuffer_add(buf, string+160, strlen(string)-160); 2729 2730 tt_int_op(206, ==, evbuffer_get_length(buf)); 2731 2732 /* First, let's test plain old copyout. */ 2733 2734 /* Copy a little from the beginning. */ 2735 tt_int_op(10, ==, evbuffer_copyout(buf, tmp, 10)); 2736 tt_int_op(0, ==, memcmp(tmp, "Still they", 10)); 2737 2738 /* Now copy more than a little from the beginning */ 2739 memset(tmp, 0, sizeof(tmp)); 2740 tt_int_op(100, ==, evbuffer_copyout(buf, tmp, 100)); 2741 tt_int_op(0, ==, memcmp(tmp, string, 100)); 2742 2743 /* Copy too much; ensure truncation. */ 2744 memset(tmp, 0, sizeof(tmp)); 2745 tt_int_op(206, ==, evbuffer_copyout(buf, tmp, 230)); 2746 tt_int_op(0, ==, memcmp(tmp, string, 206)); 2747 2748 /* That was supposed to be nondestructive, btw */ 2749 tt_int_op(206, ==, evbuffer_get_length(buf)); 2750 2751 /* Now it's time to test copyout_from! First, let's start in the 2752 * first chain. */ 2753 evbuffer_ptr_set(buf, &ptr, 15, EVBUFFER_PTR_SET); 2754 memset(tmp, 0, sizeof(tmp)); 2755 tt_int_op(10, ==, evbuffer_copyout_from(buf, &ptr, tmp, 10)); 2756 tt_int_op(0, ==, memcmp(tmp, "mish to an", 10)); 2757 2758 /* Right up to the end of the first chain */ 2759 memset(tmp, 0, sizeof(tmp)); 2760 tt_int_op(65, ==, evbuffer_copyout_from(buf, &ptr, tmp, 65)); 2761 tt_int_op(0, ==, memcmp(tmp, string+15, 65)); 2762 2763 /* Span into the second chain */ 2764 memset(tmp, 0, sizeof(tmp)); 2765 tt_int_op(90, ==, evbuffer_copyout_from(buf, &ptr, tmp, 90)); 2766 tt_int_op(0, ==, memcmp(tmp, string+15, 90)); 2767 2768 /* Span into the third chain */ 2769 memset(tmp, 0, sizeof(tmp)); 2770 tt_int_op(160, ==, evbuffer_copyout_from(buf, &ptr, tmp, 160)); 2771 tt_int_op(0, ==, memcmp(tmp, string+15, 160)); 2772 2773 /* Overrun */ 2774 memset(tmp, 0, sizeof(tmp)); 2775 tt_int_op(206-15, ==, evbuffer_copyout_from(buf, &ptr, tmp, 999)); 2776 tt_int_op(0, ==, memcmp(tmp, string+15, 206-15)); 2777 2778 /* That was supposed to be nondestructive, too */ 2779 tt_int_op(206, ==, evbuffer_get_length(buf)); 2780 2781 end: 2782 if (buf) 2783 evbuffer_free(buf); 2784 } 2785 2786 static void * 2787 setup_passthrough(const struct testcase_t *testcase) 2788 { 2789 return testcase->setup_data; 2790 } 2791 static int 2792 cleanup_passthrough(const struct testcase_t *testcase, void *ptr) 2793 { 2794 (void) ptr; 2795 return 1; 2796 } 2797 2798 static const struct testcase_setup_t nil_setup = { 2799 setup_passthrough, 2800 cleanup_passthrough 2801 }; 2802 2803 struct testcase_t evbuffer_testcases[] = { 2804 { "evbuffer", test_evbuffer, 0, NULL, NULL }, 2805 { "remove_buffer_with_empty", test_evbuffer_remove_buffer_with_empty, 0, NULL, NULL }, 2806 { "remove_buffer_with_empty2", test_evbuffer_remove_buffer_with_empty2, 0, NULL, NULL }, 2807 { "remove_buffer_with_empty3", test_evbuffer_remove_buffer_with_empty3, 0, NULL, NULL }, 2808 { "remove_buffer_with_empty_front", test_evbuffer_remove_buffer_with_empty_front, 0, NULL, NULL }, 2809 { "remove_buffer_adjust_last_with_datap_with_empty", 2810 test_evbuffer_remove_buffer_adjust_last_with_datap_with_empty, 0, NULL, NULL }, 2811 { "add_buffer_with_empty", test_evbuffer_add_buffer_with_empty, 0, NULL, NULL }, 2812 { "add_buffer_with_empty2", test_evbuffer_add_buffer_with_empty2, 0, NULL, NULL }, 2813 { "reserve2", test_evbuffer_reserve2, 0, NULL, NULL }, 2814 { "reserve_many", test_evbuffer_reserve_many, 0, NULL, NULL }, 2815 { "reserve_many2", test_evbuffer_reserve_many, 0, &nil_setup, (void*)"add" }, 2816 { "reserve_many3", test_evbuffer_reserve_many, 0, &nil_setup, (void*)"fill" }, 2817 { "reserve_with_empty", test_evbuffer_reserve_with_empty, 0, NULL, NULL }, 2818 { "reserve_invalid_last_with_datap", test_evbuffer_reserve_invalid_last_with_datap, TT_FORK, NULL, NULL }, 2819 { "expand", test_evbuffer_expand, 0, NULL, NULL }, 2820 { "expand_overflow", test_evbuffer_expand_overflow, 0, NULL, NULL }, 2821 { "add1", test_evbuffer_add1, 0, NULL, NULL }, 2822 { "add2", test_evbuffer_add2, 0, NULL, NULL }, 2823 { "reference", test_evbuffer_reference, 0, NULL, NULL }, 2824 { "reference2", test_evbuffer_reference2, 0, NULL, NULL }, 2825 { "iterative", test_evbuffer_iterative, 0, NULL, NULL }, 2826 { "readln", test_evbuffer_readln, TT_NO_LOGS, &basic_setup, NULL }, 2827 { "search_eol", test_evbuffer_search_eol, 0, NULL, NULL }, 2828 { "find", test_evbuffer_find, 0, NULL, NULL }, 2829 { "ptr_set", test_evbuffer_ptr_set, 0, NULL, NULL }, 2830 { "search", test_evbuffer_search, 0, NULL, NULL }, 2831 { "callbacks", test_evbuffer_callbacks, 0, NULL, NULL }, 2832 { "add_reference", test_evbuffer_add_reference, 0, NULL, NULL }, 2833 { "multicast", test_evbuffer_multicast, 0, NULL, NULL }, 2834 { "multicast_drain", test_evbuffer_multicast_drain, 0, NULL, NULL }, 2835 { "prepend", test_evbuffer_prepend, TT_FORK, NULL, NULL }, 2836 { "empty_reference_prepend", test_evbuffer_empty_reference_prepend, TT_FORK, NULL, NULL }, 2837 { "empty_reference_prepend_buffer", test_evbuffer_empty_reference_prepend_buffer, TT_FORK, NULL, NULL }, 2838 { "peek", test_evbuffer_peek, 0, NULL, NULL }, 2839 { "peek_first_gt", test_evbuffer_peek_first_gt, 0, NULL, NULL }, 2840 { "freeze_start", test_evbuffer_freeze, TT_NEED_SOCKETPAIR, &basic_setup, (void*)"start" }, 2841 { "freeze_end", test_evbuffer_freeze, TT_NEED_SOCKETPAIR, &basic_setup, (void*)"end" }, 2842 { "add_iovec", test_evbuffer_add_iovec, 0, NULL, NULL}, 2843 { "copyout", test_evbuffer_copyout, 0, NULL, NULL}, 2844 { "file_segment_add_cleanup_cb", test_evbuffer_file_segment_add_cleanup_cb, 0, NULL, NULL }, 2845 { "pullup_with_empty", test_evbuffer_pullup_with_empty, 0, NULL, NULL }, 2846 2847 #define ADDFILE_TEST(name, parameters) \ 2848 { name, test_evbuffer_add_file, TT_FORK|TT_NEED_BASE, \ 2849 &basic_setup, (void*)(parameters) } 2850 2851 #define ADDFILE_TEST_GROUP(name, parameters) \ 2852 ADDFILE_TEST(name "_sendfile", "sendfile " parameters), \ 2853 ADDFILE_TEST(name "_mmap", "mmap " parameters), \ 2854 ADDFILE_TEST(name "_linear", "linear " parameters) 2855 2856 ADDFILE_TEST_GROUP("add_file", ""), 2857 ADDFILE_TEST("add_file_nosegment", "default nosegment"), 2858 2859 ADDFILE_TEST_GROUP("add_big_file", "bigfile"), 2860 ADDFILE_TEST("add_big_file_nosegment", "default nosegment bigfile"), 2861 2862 ADDFILE_TEST_GROUP("add_file_offset", "bigfile map_offset"), 2863 ADDFILE_TEST("add_file_offset_nosegment", 2864 "default nosegment bigfile map_offset"), 2865 2866 ADDFILE_TEST_GROUP("add_file_offset2", "bigfile offset_in_segment"), 2867 2868 ADDFILE_TEST_GROUP("add_file_offset3", 2869 "bigfile offset_in_segment map_offset"), 2870 2871 END_OF_TESTCASES 2872 }; 2873