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