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