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