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