1 /* $NetBSD: regress_buffer.c,v 1.2 2013/04/11 16:56:42 christos Exp $ */ 2 /* 3 * Copyright (c) 2003-2007 Niels Provos <provos@citi.umich.edu> 4 * Copyright (c) 2007-2012 Niels Provos and Nick Mathewson 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 2. Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 3. The name of the author may not be used to endorse or promote products 15 * derived from this software without specific prior written permission. 16 * 17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 */ 28 29 #ifdef WIN32 30 #include <winsock2.h> 31 #include <windows.h> 32 #endif 33 34 #include "event2/event-config.h" 35 #include <sys/cdefs.h> 36 __RCSID("$NetBSD: regress_buffer.c,v 1.2 2013/04/11 16:56:42 christos Exp $"); 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 "evbuffer-internal.h" 63 #include "log-internal.h" 64 65 #include "regress.h" 66 67 /* Validates that an evbuffer is good. Returns false if it isn't, true if it 68 * is*/ 69 static int 70 _evbuffer_validate(struct evbuffer *buf) 71 { 72 struct evbuffer_chain *chain; 73 size_t sum = 0; 74 int found_last_with_datap = 0; 75 76 if (buf->first == NULL) { 77 tt_assert(buf->last == NULL); 78 tt_assert(buf->total_len == 0); 79 } 80 81 chain = buf->first; 82 83 tt_assert(buf->last_with_datap); 84 if (buf->last_with_datap == &buf->first) 85 found_last_with_datap = 1; 86 87 while (chain != NULL) { 88 if (&chain->next == buf->last_with_datap) 89 found_last_with_datap = 1; 90 sum += chain->off; 91 if (chain->next == NULL) { 92 tt_assert(buf->last == chain); 93 } 94 tt_assert(chain->buffer_len >= chain->misalign + chain->off); 95 chain = chain->next; 96 } 97 98 if (buf->first) 99 tt_assert(*buf->last_with_datap); 100 101 if (*buf->last_with_datap) { 102 chain = *buf->last_with_datap; 103 if (chain->off == 0 || buf->total_len == 0) { 104 tt_assert(chain->off == 0) 105 tt_assert(chain == buf->first); 106 tt_assert(buf->total_len == 0); 107 } 108 chain = chain->next; 109 while (chain != NULL) { 110 tt_assert(chain->off == 0); 111 chain = chain->next; 112 } 113 } else { 114 tt_assert(buf->last_with_datap == &buf->first); 115 } 116 tt_assert(found_last_with_datap); 117 118 tt_assert(sum == buf->total_len); 119 return 1; 120 end: 121 return 0; 122 } 123 124 static void 125 evbuffer_get_waste(struct evbuffer *buf, size_t *allocatedp, size_t *wastedp, size_t *usedp) 126 { 127 struct evbuffer_chain *chain; 128 size_t a, w, u; 129 int n = 0; 130 u = a = w = 0; 131 132 chain = buf->first; 133 /* skip empty at start */ 134 while (chain && chain->off==0) { 135 ++n; 136 a += chain->buffer_len; 137 chain = chain->next; 138 } 139 /* first nonempty chain: stuff at the end only is wasted. */ 140 if (chain) { 141 ++n; 142 a += chain->buffer_len; 143 u += chain->off; 144 if (chain->next && chain->next->off) 145 w += (size_t)(chain->buffer_len - (chain->misalign + chain->off)); 146 chain = chain->next; 147 } 148 /* subsequent nonempty chains */ 149 while (chain && chain->off) { 150 ++n; 151 a += chain->buffer_len; 152 w += (size_t)chain->misalign; 153 u += chain->off; 154 if (chain->next && chain->next->off) 155 w += (size_t) (chain->buffer_len - (chain->misalign + chain->off)); 156 chain = chain->next; 157 } 158 /* subsequent empty chains */ 159 while (chain) { 160 ++n; 161 a += chain->buffer_len; 162 } 163 *allocatedp = a; 164 *wastedp = w; 165 *usedp = u; 166 } 167 168 #define evbuffer_validate(buf) \ 169 TT_STMT_BEGIN if (!_evbuffer_validate(buf)) TT_DIE(("Buffer format invalid")); TT_STMT_END 170 171 static void 172 test_evbuffer(void *ptr) 173 { 174 static char buffer[512], *tmp; 175 struct evbuffer *evb = evbuffer_new(); 176 struct evbuffer *evb_two = evbuffer_new(); 177 size_t sz_tmp; 178 int i; 179 180 evbuffer_validate(evb); 181 evbuffer_add_printf(evb, "%s/%d", "hello", 1); 182 evbuffer_validate(evb); 183 184 tt_assert(evbuffer_get_length(evb) == 7); 185 tt_assert(!memcmp((char*)EVBUFFER_DATA(evb), "hello/1", 1)); 186 187 evbuffer_add_buffer(evb, evb_two); 188 evbuffer_validate(evb); 189 190 evbuffer_drain(evb, strlen("hello/")); 191 evbuffer_validate(evb); 192 tt_assert(evbuffer_get_length(evb) == 1); 193 tt_assert(!memcmp((char*)EVBUFFER_DATA(evb), "1", 1)); 194 195 evbuffer_add_printf(evb_two, "%s", "/hello"); 196 evbuffer_validate(evb); 197 evbuffer_add_buffer(evb, evb_two); 198 evbuffer_validate(evb); 199 200 tt_assert(evbuffer_get_length(evb_two) == 0); 201 tt_assert(evbuffer_get_length(evb) == 7); 202 tt_assert(!memcmp((char*)EVBUFFER_DATA(evb), "1/hello", 7) != 0); 203 204 memset(buffer, 0, sizeof(buffer)); 205 evbuffer_add(evb, buffer, sizeof(buffer)); 206 evbuffer_validate(evb); 207 tt_assert(evbuffer_get_length(evb) == 7 + 512); 208 209 tmp = (char *)evbuffer_pullup(evb, 7 + 512); 210 tt_assert(tmp); 211 tt_assert(!strncmp(tmp, "1/hello", 7)); 212 tt_assert(!memcmp(tmp + 7, buffer, sizeof(buffer))); 213 evbuffer_validate(evb); 214 215 evbuffer_prepend(evb, "something", 9); 216 evbuffer_validate(evb); 217 evbuffer_prepend(evb, "else", 4); 218 evbuffer_validate(evb); 219 220 tmp = (char *)evbuffer_pullup(evb, 4 + 9 + 7); 221 tt_assert(!strncmp(tmp, "elsesomething1/hello", 4 + 9 + 7)); 222 evbuffer_validate(evb); 223 224 evbuffer_drain(evb, -1); 225 evbuffer_validate(evb); 226 evbuffer_drain(evb_two, -1); 227 evbuffer_validate(evb); 228 229 for (i = 0; i < 3; ++i) { 230 evbuffer_add(evb_two, buffer, sizeof(buffer)); 231 evbuffer_validate(evb_two); 232 evbuffer_add_buffer(evb, evb_two); 233 evbuffer_validate(evb); 234 evbuffer_validate(evb_two); 235 } 236 237 tt_assert(evbuffer_get_length(evb_two) == 0); 238 tt_assert(evbuffer_get_length(evb) == i * sizeof(buffer)); 239 240 /* test remove buffer */ 241 sz_tmp = (size_t)(sizeof(buffer)*2.5); 242 evbuffer_remove_buffer(evb, evb_two, sz_tmp); 243 tt_assert(evbuffer_get_length(evb_two) == sz_tmp); 244 tt_assert(evbuffer_get_length(evb) == sizeof(buffer) / 2); 245 evbuffer_validate(evb); 246 247 if (memcmp(evbuffer_pullup( 248 evb, -1), buffer, sizeof(buffer) / 2) != 0 || 249 memcmp(evbuffer_pullup( 250 evb_two, -1), buffer, sizeof(buffer) != 0)) 251 tt_abort_msg("Pullup did not preserve content"); 252 253 evbuffer_validate(evb); 254 255 256 /* testing one-vector reserve and commit */ 257 { 258 struct evbuffer_iovec v[1]; 259 char *buf; 260 int ii, j, r; 261 262 for (ii = 0; ii < 3; ++ii) { 263 r = evbuffer_reserve_space(evb, 10000, v, 1); 264 tt_int_op(r, ==, 1); 265 tt_assert(v[0].iov_len >= 10000); 266 tt_assert(v[0].iov_base != NULL); 267 268 evbuffer_validate(evb); 269 buf = v[0].iov_base; 270 for (j = 0; j < 10000; ++j) { 271 buf[j] = j; 272 } 273 evbuffer_validate(evb); 274 275 tt_int_op(evbuffer_commit_space(evb, v, 1), ==, 0); 276 evbuffer_validate(evb); 277 278 tt_assert(evbuffer_get_length(evb) >= 10000); 279 280 evbuffer_drain(evb, j * 5000); 281 evbuffer_validate(evb); 282 } 283 } 284 285 end: 286 evbuffer_free(evb); 287 evbuffer_free(evb_two); 288 } 289 290 static void 291 no_cleanup(const void *data, size_t datalen, void *extra) 292 { 293 } 294 295 static void 296 test_evbuffer_remove_buffer_with_empty(void *ptr) 297 { 298 struct evbuffer *src = evbuffer_new(); 299 struct evbuffer *dst = evbuffer_new(); 300 char buf[2]; 301 302 evbuffer_validate(src); 303 evbuffer_validate(dst); 304 305 /* setup the buffers */ 306 /* we need more data in src than we will move later */ 307 evbuffer_add_reference(src, buf, sizeof(buf), no_cleanup, NULL); 308 evbuffer_add_reference(src, buf, sizeof(buf), no_cleanup, NULL); 309 /* we need one buffer in dst and one empty buffer at the end */ 310 evbuffer_add(dst, buf, sizeof(buf)); 311 evbuffer_add_reference(dst, buf, 0, no_cleanup, NULL); 312 313 evbuffer_validate(src); 314 evbuffer_validate(dst); 315 316 /* move three bytes over */ 317 evbuffer_remove_buffer(src, dst, 3); 318 319 evbuffer_validate(src); 320 evbuffer_validate(dst); 321 322 end: 323 evbuffer_free(src); 324 evbuffer_free(dst); 325 } 326 327 static void 328 test_evbuffer_reserve2(void *ptr) 329 { 330 /* Test the two-vector cases of reserve/commit. */ 331 struct evbuffer *buf = evbuffer_new(); 332 int n, i; 333 struct evbuffer_iovec v[2]; 334 size_t remaining; 335 char *cp, *cp2; 336 337 /* First chunk will necessarily be one chunk. Use 512 bytes of it.*/ 338 n = evbuffer_reserve_space(buf, 1024, v, 2); 339 tt_int_op(n, ==, 1); 340 tt_int_op(evbuffer_get_length(buf), ==, 0); 341 tt_assert(v[0].iov_base != NULL); 342 tt_int_op(v[0].iov_len, >=, 1024); 343 memset(v[0].iov_base, 'X', 512); 344 cp = v[0].iov_base; 345 remaining = v[0].iov_len - 512; 346 v[0].iov_len = 512; 347 evbuffer_validate(buf); 348 tt_int_op(0, ==, evbuffer_commit_space(buf, v, 1)); 349 tt_int_op(evbuffer_get_length(buf), ==, 512); 350 evbuffer_validate(buf); 351 352 /* Ask for another same-chunk request, in an existing chunk. Use 8 353 * bytes of it. */ 354 n = evbuffer_reserve_space(buf, 32, v, 2); 355 tt_int_op(n, ==, 1); 356 tt_assert(cp + 512 == v[0].iov_base); 357 tt_int_op(remaining, ==, v[0].iov_len); 358 memset(v[0].iov_base, 'Y', 8); 359 v[0].iov_len = 8; 360 tt_int_op(0, ==, evbuffer_commit_space(buf, v, 1)); 361 tt_int_op(evbuffer_get_length(buf), ==, 520); 362 remaining -= 8; 363 evbuffer_validate(buf); 364 365 /* Now ask for a request that will be split. Use only one byte of it, 366 though. */ 367 n = evbuffer_reserve_space(buf, remaining+64, v, 2); 368 tt_int_op(n, ==, 2); 369 tt_assert(cp + 520 == v[0].iov_base); 370 tt_int_op(remaining, ==, v[0].iov_len); 371 tt_assert(v[1].iov_base); 372 tt_assert(v[1].iov_len >= 64); 373 cp2 = v[1].iov_base; 374 memset(v[0].iov_base, 'Z', 1); 375 v[0].iov_len = 1; 376 tt_int_op(0, ==, evbuffer_commit_space(buf, v, 1)); 377 tt_int_op(evbuffer_get_length(buf), ==, 521); 378 remaining -= 1; 379 evbuffer_validate(buf); 380 381 /* Now ask for a request that will be split. Use some of the first 382 * part and some of the second. */ 383 n = evbuffer_reserve_space(buf, remaining+64, v, 2); 384 evbuffer_validate(buf); 385 tt_int_op(n, ==, 2); 386 tt_assert(cp + 521 == v[0].iov_base); 387 tt_int_op(remaining, ==, v[0].iov_len); 388 tt_assert(v[1].iov_base == cp2); 389 tt_assert(v[1].iov_len >= 64); 390 memset(v[0].iov_base, 'W', 400); 391 v[0].iov_len = 400; 392 memset(v[1].iov_base, 'x', 60); 393 v[1].iov_len = 60; 394 tt_int_op(0, ==, evbuffer_commit_space(buf, v, 2)); 395 tt_int_op(evbuffer_get_length(buf), ==, 981); 396 evbuffer_validate(buf); 397 398 /* Now peek to make sure stuff got made how we like. */ 399 memset(v,0,sizeof(v)); 400 n = evbuffer_peek(buf, -1, NULL, v, 2); 401 tt_int_op(n, ==, 2); 402 tt_int_op(v[0].iov_len, ==, 921); 403 tt_int_op(v[1].iov_len, ==, 60); 404 405 cp = v[0].iov_base; 406 for (i=0; i<512; ++i) 407 tt_int_op(cp[i], ==, 'X'); 408 for (i=512; i<520; ++i) 409 tt_int_op(cp[i], ==, 'Y'); 410 for (i=520; i<521; ++i) 411 tt_int_op(cp[i], ==, 'Z'); 412 for (i=521; i<921; ++i) 413 tt_int_op(cp[i], ==, 'W'); 414 415 cp = v[1].iov_base; 416 for (i=0; i<60; ++i) 417 tt_int_op(cp[i], ==, 'x'); 418 419 end: 420 evbuffer_free(buf); 421 } 422 423 static void 424 test_evbuffer_reserve_many(void *ptr) 425 { 426 /* This is a glass-box test to handle expanding a buffer with more 427 * chunks and reallocating chunks as needed */ 428 struct evbuffer *buf = evbuffer_new(); 429 struct evbuffer_iovec v[8]; 430 int n; 431 size_t sz; 432 int add_data = ptr && !strcmp(ptr, "add"); 433 int fill_first = ptr && !strcmp(ptr, "fill"); 434 char *cp1, *cp2; 435 436 /* When reserving the the first chunk, we just allocate it */ 437 n = evbuffer_reserve_space(buf, 128, v, 2); 438 evbuffer_validate(buf); 439 tt_int_op(n, ==, 1); 440 tt_assert(v[0].iov_len >= 128); 441 sz = v[0].iov_len; 442 cp1 = v[0].iov_base; 443 if (add_data) { 444 *(char*)v[0].iov_base = 'X'; 445 v[0].iov_len = 1; 446 n = evbuffer_commit_space(buf, v, 1); 447 tt_int_op(n, ==, 0); 448 } else if (fill_first) { 449 memset(v[0].iov_base, 'X', v[0].iov_len); 450 n = evbuffer_commit_space(buf, v, 1); 451 tt_int_op(n, ==, 0); 452 n = evbuffer_reserve_space(buf, 128, v, 2); 453 tt_int_op(n, ==, 1); 454 sz = v[0].iov_len; 455 tt_assert(v[0].iov_base != cp1); 456 cp1 = v[0].iov_base; 457 } 458 459 /* Make another chunk get added. */ 460 n = evbuffer_reserve_space(buf, sz+128, v, 2); 461 evbuffer_validate(buf); 462 tt_int_op(n, ==, 2); 463 sz = v[0].iov_len + v[1].iov_len; 464 tt_int_op(sz, >=, v[0].iov_len+128); 465 if (add_data) { 466 tt_assert(v[0].iov_base == cp1 + 1); 467 } else { 468 tt_assert(v[0].iov_base == cp1); 469 } 470 cp1 = v[0].iov_base; 471 cp2 = v[1].iov_base; 472 473 /* And a third chunk. */ 474 n = evbuffer_reserve_space(buf, sz+128, v, 3); 475 evbuffer_validate(buf); 476 tt_int_op(n, ==, 3); 477 tt_assert(cp1 == v[0].iov_base); 478 tt_assert(cp2 == v[1].iov_base); 479 sz = v[0].iov_len + v[1].iov_len + v[2].iov_len; 480 481 /* Now force a reallocation by asking for more space in only 2 482 * buffers. */ 483 n = evbuffer_reserve_space(buf, sz+128, v, 2); 484 evbuffer_validate(buf); 485 if (add_data) { 486 tt_int_op(n, ==, 2); 487 tt_assert(cp1 == v[0].iov_base); 488 } else { 489 tt_int_op(n, ==, 1); 490 } 491 492 end: 493 evbuffer_free(buf); 494 } 495 496 static void 497 test_evbuffer_expand(void *ptr) 498 { 499 char data[4096]; 500 struct evbuffer *buf; 501 size_t a,w,u; 502 void *buffer; 503 504 memset(data, 'X', sizeof(data)); 505 506 /* Make sure that expand() works on an empty buffer */ 507 buf = evbuffer_new(); 508 tt_int_op(evbuffer_expand(buf, 20000), ==, 0); 509 evbuffer_validate(buf); 510 a=w=u=0; 511 evbuffer_get_waste(buf, &a,&w,&u); 512 tt_assert(w == 0); 513 tt_assert(u == 0); 514 tt_assert(a >= 20000); 515 tt_assert(buf->first); 516 tt_assert(buf->first == buf->last); 517 tt_assert(buf->first->off == 0); 518 tt_assert(buf->first->buffer_len >= 20000); 519 520 /* Make sure that expand() works as a no-op when there's enough 521 * contiguous space already. */ 522 buffer = buf->first->buffer; 523 evbuffer_add(buf, data, 1024); 524 tt_int_op(evbuffer_expand(buf, 1024), ==, 0); 525 tt_assert(buf->first->buffer == buffer); 526 evbuffer_validate(buf); 527 evbuffer_free(buf); 528 529 /* Make sure that expand() can work by moving misaligned data 530 * when it makes sense to do so. */ 531 buf = evbuffer_new(); 532 evbuffer_add(buf, data, 400); 533 { 534 int n = (int)(buf->first->buffer_len - buf->first->off - 1); 535 tt_assert(n < (int)sizeof(data)); 536 evbuffer_add(buf, data, n); 537 } 538 tt_assert(buf->first == buf->last); 539 tt_assert(buf->first->off == buf->first->buffer_len - 1); 540 evbuffer_drain(buf, buf->first->off - 1); 541 tt_assert(1 == evbuffer_get_length(buf)); 542 tt_assert(buf->first->misalign > 0); 543 tt_assert(buf->first->off == 1); 544 buffer = buf->first->buffer; 545 tt_assert(evbuffer_expand(buf, 40) == 0); 546 tt_assert(buf->first == buf->last); 547 tt_assert(buf->first->off == 1); 548 tt_assert(buf->first->buffer == buffer); 549 tt_assert(buf->first->misalign == 0); 550 evbuffer_validate(buf); 551 evbuffer_free(buf); 552 553 /* add, expand, pull-up: This used to crash libevent. */ 554 buf = evbuffer_new(); 555 556 evbuffer_add(buf, data, sizeof(data)); 557 evbuffer_add(buf, data, sizeof(data)); 558 evbuffer_add(buf, data, sizeof(data)); 559 560 evbuffer_validate(buf); 561 evbuffer_expand(buf, 1024); 562 evbuffer_validate(buf); 563 evbuffer_pullup(buf, -1); 564 evbuffer_validate(buf); 565 566 end: 567 evbuffer_free(buf); 568 } 569 570 571 static int reference_cb_called; 572 static void 573 reference_cb(const void *data, size_t len, void *extra) 574 { 575 tt_str_op(data, ==, "this is what we add as read-only memory."); 576 tt_int_op(len, ==, strlen(data)); 577 tt_want(extra == (void *)0xdeadaffe); 578 ++reference_cb_called; 579 end: 580 ; 581 } 582 583 static void 584 test_evbuffer_reference(void *ptr) 585 { 586 struct evbuffer *src = evbuffer_new(); 587 struct evbuffer *dst = evbuffer_new(); 588 struct evbuffer_iovec v[1]; 589 const char *data = "this is what we add as read-only memory."; 590 reference_cb_called = 0; 591 592 tt_assert(evbuffer_add_reference(src, data, strlen(data), 593 reference_cb, (void *)0xdeadaffe) != -1); 594 595 evbuffer_reserve_space(dst, strlen(data), v, 1); 596 tt_assert(evbuffer_remove(src, v[0].iov_base, 10) != -1); 597 598 evbuffer_validate(src); 599 evbuffer_validate(dst); 600 601 /* make sure that we don't write data at the beginning */ 602 evbuffer_prepend(src, "aaaaa", 5); 603 evbuffer_validate(src); 604 evbuffer_drain(src, 5); 605 606 tt_assert(evbuffer_remove(src, ((char*)(v[0].iov_base)) + 10, 607 strlen(data) - 10) != -1); 608 609 v[0].iov_len = strlen(data); 610 611 evbuffer_commit_space(dst, v, 1); 612 evbuffer_validate(src); 613 evbuffer_validate(dst); 614 615 tt_int_op(reference_cb_called, ==, 1); 616 617 tt_assert(!memcmp(evbuffer_pullup(dst, strlen(data)), 618 data, strlen(data))); 619 evbuffer_validate(dst); 620 621 end: 622 evbuffer_free(dst); 623 evbuffer_free(src); 624 } 625 626 int _evbuffer_testing_use_sendfile(void); 627 int _evbuffer_testing_use_mmap(void); 628 int _evbuffer_testing_use_linear_file_access(void); 629 630 static void 631 test_evbuffer_add_file(void *ptr) 632 { 633 const char *impl = ptr; 634 struct evbuffer *src = evbuffer_new(); 635 const char *data = "this is what we add as file system data."; 636 size_t datalen; 637 const char *compare; 638 int fd = -1; 639 evutil_socket_t xpair[2] = {-1, -1}; 640 int r=0, n_written=0; 641 642 /* Add a test for a big file. XXXX */ 643 644 tt_assert(impl); 645 if (!strcmp(impl, "sendfile")) { 646 if (!_evbuffer_testing_use_sendfile()) 647 tt_skip(); 648 TT_BLATHER(("Using sendfile-based implementaion")); 649 } else if (!strcmp(impl, "mmap")) { 650 if (!_evbuffer_testing_use_mmap()) 651 tt_skip(); 652 TT_BLATHER(("Using mmap-based implementaion")); 653 } else if (!strcmp(impl, "linear")) { 654 if (!_evbuffer_testing_use_linear_file_access()) 655 tt_skip(); 656 TT_BLATHER(("Using read-based implementaion")); 657 } else { 658 TT_DIE(("Didn't recognize the implementation")); 659 } 660 661 /* Say that it drains to a fd so that we can use sendfile. */ 662 evbuffer_set_flags(src, EVBUFFER_FLAG_DRAINS_TO_FD); 663 664 #if defined(_EVENT_HAVE_SENDFILE) && defined(__sun__) && defined(__svr4__) 665 /* We need to use a pair of AF_INET sockets, since Solaris 666 doesn't support sendfile() over AF_UNIX. */ 667 if (evutil_ersatz_socketpair(AF_INET, SOCK_STREAM, 0, xpair) == -1) 668 tt_abort_msg("ersatz_socketpair failed"); 669 #else 670 if (evutil_socketpair(AF_UNIX, SOCK_STREAM, 0, xpair) == -1) 671 tt_abort_msg("socketpair failed"); 672 #endif 673 674 datalen = strlen(data); 675 fd = regress_make_tmpfile(data, datalen); 676 677 tt_assert(fd != -1); 678 679 tt_assert(evbuffer_add_file(src, fd, 0, datalen) != -1); 680 681 evbuffer_validate(src); 682 683 while (evbuffer_get_length(src) && 684 (r = evbuffer_write(src, xpair[0])) > 0) { 685 evbuffer_validate(src); 686 n_written += r; 687 } 688 tt_int_op(r, !=, -1); 689 tt_int_op(n_written, ==, datalen); 690 691 evbuffer_validate(src); 692 tt_int_op(evbuffer_read(src, xpair[1], (int)strlen(data)), ==, datalen); 693 evbuffer_validate(src); 694 compare = (char *)evbuffer_pullup(src, datalen); 695 tt_assert(compare != NULL); 696 if (memcmp(compare, data, datalen)) 697 tt_abort_msg("Data from add_file differs."); 698 699 evbuffer_validate(src); 700 end: 701 if (xpair[0] >= 0) 702 evutil_closesocket(xpair[0]); 703 if (xpair[1] >= 0) 704 evutil_closesocket(xpair[1]); 705 evbuffer_free(src); 706 } 707 708 #ifndef _EVENT_DISABLE_MM_REPLACEMENT 709 static void * 710 failing_malloc(size_t how_much) 711 { 712 errno = ENOMEM; 713 return NULL; 714 } 715 #endif 716 717 static void 718 test_evbuffer_readln(void *ptr) 719 { 720 struct evbuffer *evb = evbuffer_new(); 721 struct evbuffer *evb_tmp = evbuffer_new(); 722 const char *s; 723 char *cp = NULL; 724 size_t sz; 725 726 #define tt_line_eq(content) \ 727 TT_STMT_BEGIN \ 728 if (!cp || sz != strlen(content) || strcmp(cp, content)) { \ 729 TT_DIE(("Wanted %s; got %s [%d]", content, cp, (int)sz)); \ 730 } \ 731 TT_STMT_END 732 733 /* Test EOL_ANY. */ 734 s = "complex silly newline\r\n\n\r\n\n\rmore\0\n"; 735 evbuffer_add(evb, s, strlen(s)+2); 736 evbuffer_validate(evb); 737 cp = evbuffer_readln(evb, &sz, EVBUFFER_EOL_ANY); 738 tt_line_eq("complex silly newline"); 739 free(cp); 740 evbuffer_validate(evb); 741 cp = evbuffer_readln(evb, &sz, EVBUFFER_EOL_ANY); 742 if (!cp || sz != 5 || memcmp(cp, "more\0\0", 6)) 743 tt_abort_msg("Not as expected"); 744 tt_uint_op(evbuffer_get_length(evb), ==, 0); 745 evbuffer_validate(evb); 746 s = "\nno newline"; 747 evbuffer_add(evb, s, strlen(s)); 748 free(cp); 749 evbuffer_validate(evb); 750 cp = evbuffer_readln(evb, &sz, EVBUFFER_EOL_ANY); 751 tt_line_eq(""); 752 free(cp); 753 evbuffer_validate(evb); 754 cp = evbuffer_readln(evb, &sz, EVBUFFER_EOL_ANY); 755 tt_assert(!cp); 756 evbuffer_validate(evb); 757 evbuffer_drain(evb, evbuffer_get_length(evb)); 758 tt_assert(evbuffer_get_length(evb) == 0); 759 evbuffer_validate(evb); 760 761 /* Test EOL_CRLF */ 762 s = "Line with\rin the middle\nLine with good crlf\r\n\nfinal\n"; 763 evbuffer_add(evb, s, strlen(s)); 764 evbuffer_validate(evb); 765 cp = evbuffer_readln(evb, &sz, EVBUFFER_EOL_CRLF); 766 tt_line_eq("Line with\rin the middle"); 767 free(cp); 768 evbuffer_validate(evb); 769 770 cp = evbuffer_readln(evb, &sz, EVBUFFER_EOL_CRLF); 771 tt_line_eq("Line with good crlf"); 772 free(cp); 773 evbuffer_validate(evb); 774 775 cp = evbuffer_readln(evb, &sz, EVBUFFER_EOL_CRLF); 776 tt_line_eq(""); 777 free(cp); 778 evbuffer_validate(evb); 779 780 cp = evbuffer_readln(evb, &sz, EVBUFFER_EOL_CRLF); 781 tt_line_eq("final"); 782 s = "x"; 783 evbuffer_validate(evb); 784 evbuffer_add(evb, s, 1); 785 evbuffer_validate(evb); 786 free(cp); 787 cp = evbuffer_readln(evb, &sz, EVBUFFER_EOL_CRLF); 788 tt_assert(!cp); 789 evbuffer_validate(evb); 790 791 /* Test CRLF_STRICT */ 792 s = " and a bad crlf\nand a good one\r\n\r\nMore\r"; 793 evbuffer_add(evb, s, strlen(s)); 794 evbuffer_validate(evb); 795 cp = evbuffer_readln(evb, &sz, EVBUFFER_EOL_CRLF_STRICT); 796 tt_line_eq("x and a bad crlf\nand a good one"); 797 free(cp); 798 evbuffer_validate(evb); 799 800 cp = evbuffer_readln(evb, &sz, EVBUFFER_EOL_CRLF_STRICT); 801 tt_line_eq(""); 802 free(cp); 803 evbuffer_validate(evb); 804 805 cp = evbuffer_readln(evb, &sz, EVBUFFER_EOL_CRLF_STRICT); 806 tt_assert(!cp); 807 evbuffer_validate(evb); 808 evbuffer_add(evb, "\n", 1); 809 evbuffer_validate(evb); 810 811 cp = evbuffer_readln(evb, &sz, EVBUFFER_EOL_CRLF_STRICT); 812 tt_line_eq("More"); 813 free(cp); 814 tt_assert(evbuffer_get_length(evb) == 0); 815 evbuffer_validate(evb); 816 817 s = "An internal CR\r is not an eol\r\nNor is a lack of one"; 818 evbuffer_add(evb, s, strlen(s)); 819 cp = evbuffer_readln(evb, &sz, EVBUFFER_EOL_CRLF_STRICT); 820 tt_line_eq("An internal CR\r is not an eol"); 821 free(cp); 822 evbuffer_validate(evb); 823 824 cp = evbuffer_readln(evb, &sz, EVBUFFER_EOL_CRLF_STRICT); 825 tt_assert(!cp); 826 evbuffer_validate(evb); 827 828 evbuffer_add(evb, "\r\n", 2); 829 evbuffer_validate(evb); 830 cp = evbuffer_readln(evb, &sz, EVBUFFER_EOL_CRLF_STRICT); 831 tt_line_eq("Nor is a lack of one"); 832 free(cp); 833 tt_assert(evbuffer_get_length(evb) == 0); 834 evbuffer_validate(evb); 835 836 /* Test LF */ 837 s = "An\rand a nl\n\nText"; 838 evbuffer_add(evb, s, strlen(s)); 839 evbuffer_validate(evb); 840 841 cp = evbuffer_readln(evb, &sz, EVBUFFER_EOL_LF); 842 tt_line_eq("An\rand a nl"); 843 free(cp); 844 evbuffer_validate(evb); 845 846 cp = evbuffer_readln(evb, &sz, EVBUFFER_EOL_LF); 847 tt_line_eq(""); 848 free(cp); 849 evbuffer_validate(evb); 850 851 cp = evbuffer_readln(evb, &sz, EVBUFFER_EOL_LF); 852 tt_assert(!cp); 853 free(cp); 854 evbuffer_add(evb, "\n", 1); 855 evbuffer_validate(evb); 856 cp = evbuffer_readln(evb, &sz, EVBUFFER_EOL_LF); 857 tt_line_eq("Text"); 858 free(cp); 859 evbuffer_validate(evb); 860 861 /* Test CRLF_STRICT - across boundaries*/ 862 s = " and a bad crlf\nand a good one\r"; 863 evbuffer_add(evb_tmp, s, strlen(s)); 864 evbuffer_validate(evb); 865 evbuffer_add_buffer(evb, evb_tmp); 866 evbuffer_validate(evb); 867 s = "\n\r"; 868 evbuffer_add(evb_tmp, s, strlen(s)); 869 evbuffer_validate(evb); 870 evbuffer_add_buffer(evb, evb_tmp); 871 evbuffer_validate(evb); 872 s = "\nMore\r"; 873 evbuffer_add(evb_tmp, s, strlen(s)); 874 evbuffer_validate(evb); 875 evbuffer_add_buffer(evb, evb_tmp); 876 evbuffer_validate(evb); 877 878 cp = evbuffer_readln(evb, &sz, EVBUFFER_EOL_CRLF_STRICT); 879 tt_line_eq(" and a bad crlf\nand a good one"); 880 free(cp); 881 evbuffer_validate(evb); 882 883 cp = evbuffer_readln(evb, &sz, EVBUFFER_EOL_CRLF_STRICT); 884 tt_line_eq(""); 885 free(cp); 886 evbuffer_validate(evb); 887 888 cp = evbuffer_readln(evb, &sz, EVBUFFER_EOL_CRLF_STRICT); 889 tt_assert(!cp); 890 free(cp); 891 evbuffer_validate(evb); 892 evbuffer_add(evb, "\n", 1); 893 evbuffer_validate(evb); 894 cp = evbuffer_readln(evb, &sz, EVBUFFER_EOL_CRLF_STRICT); 895 tt_line_eq("More"); 896 free(cp); cp = NULL; 897 evbuffer_validate(evb); 898 tt_assert(evbuffer_get_length(evb) == 0); 899 900 /* Test memory problem*/ 901 s = "one line\ntwo line\nblue line"; 902 evbuffer_add(evb_tmp, s, strlen(s)); 903 evbuffer_validate(evb); 904 evbuffer_add_buffer(evb, evb_tmp); 905 evbuffer_validate(evb); 906 907 cp = evbuffer_readln(evb, &sz, EVBUFFER_EOL_LF); 908 tt_line_eq("one line"); 909 free(cp); cp = NULL; 910 evbuffer_validate(evb); 911 912 /* the next call to readline should fail */ 913 #ifndef _EVENT_DISABLE_MM_REPLACEMENT 914 event_set_mem_functions(failing_malloc, realloc, free); 915 cp = evbuffer_readln(evb, &sz, EVBUFFER_EOL_LF); 916 tt_assert(cp == NULL); 917 evbuffer_validate(evb); 918 919 /* now we should get the next line back */ 920 event_set_mem_functions(malloc, realloc, free); 921 #endif 922 cp = evbuffer_readln(evb, &sz, EVBUFFER_EOL_LF); 923 tt_line_eq("two line"); 924 free(cp); cp = NULL; 925 evbuffer_validate(evb); 926 927 end: 928 evbuffer_free(evb); 929 evbuffer_free(evb_tmp); 930 if (cp) free(cp); 931 } 932 933 static void 934 test_evbuffer_search_eol(void *ptr) 935 { 936 struct evbuffer *buf = evbuffer_new(); 937 struct evbuffer_ptr ptr1, ptr2; 938 const char *s; 939 size_t eol_len; 940 941 s = "string! \r\n\r\nx\n"; 942 evbuffer_add(buf, s, strlen(s)); 943 eol_len = -1; 944 ptr1 = evbuffer_search_eol(buf, NULL, &eol_len, EVBUFFER_EOL_CRLF); 945 tt_int_op(ptr1.pos, ==, 8); 946 tt_int_op(eol_len, ==, 2); 947 948 eol_len = -1; 949 ptr2 = evbuffer_search_eol(buf, &ptr1, &eol_len, EVBUFFER_EOL_CRLF); 950 tt_int_op(ptr2.pos, ==, 8); 951 tt_int_op(eol_len, ==, 2); 952 953 evbuffer_ptr_set(buf, &ptr1, 1, EVBUFFER_PTR_ADD); 954 eol_len = -1; 955 ptr2 = evbuffer_search_eol(buf, &ptr1, &eol_len, EVBUFFER_EOL_CRLF); 956 tt_int_op(ptr2.pos, ==, 9); 957 tt_int_op(eol_len, ==, 1); 958 959 eol_len = -1; 960 ptr2 = evbuffer_search_eol(buf, &ptr1, &eol_len, EVBUFFER_EOL_CRLF_STRICT); 961 tt_int_op(ptr2.pos, ==, 10); 962 tt_int_op(eol_len, ==, 2); 963 964 eol_len = -1; 965 ptr1 = evbuffer_search_eol(buf, NULL, &eol_len, EVBUFFER_EOL_LF); 966 tt_int_op(ptr1.pos, ==, 9); 967 tt_int_op(eol_len, ==, 1); 968 969 eol_len = -1; 970 ptr2 = evbuffer_search_eol(buf, &ptr1, &eol_len, EVBUFFER_EOL_LF); 971 tt_int_op(ptr2.pos, ==, 9); 972 tt_int_op(eol_len, ==, 1); 973 974 evbuffer_ptr_set(buf, &ptr1, 1, EVBUFFER_PTR_ADD); 975 eol_len = -1; 976 ptr2 = evbuffer_search_eol(buf, &ptr1, &eol_len, EVBUFFER_EOL_LF); 977 tt_int_op(ptr2.pos, ==, 11); 978 tt_int_op(eol_len, ==, 1); 979 980 end: 981 evbuffer_free(buf); 982 } 983 984 static void 985 test_evbuffer_iterative(void *ptr) 986 { 987 struct evbuffer *buf = evbuffer_new(); 988 const char *abc = "abcdefghijklmnopqrstvuwxyzabcdefghijklmnopqrstvuwxyzabcdefghijklmnopqrstvuwxyzabcdefghijklmnopqrstvuwxyz"; 989 unsigned i, j, sum, n; 990 991 sum = 0; 992 n = 0; 993 for (i = 0; i < 1000; ++i) { 994 for (j = 1; j < strlen(abc); ++j) { 995 evbuffer_add_printf(buf, "%*.*s", j, j, abc); 996 997 /* Only check for rep violations every so often. 998 Walking over the whole list of chains can get 999 pretty expensive as it gets long. 1000 */ 1001 if ((n % 337) == 0) 1002 evbuffer_validate(buf); 1003 1004 sum += j; 1005 n++; 1006 } 1007 } 1008 evbuffer_validate(buf); 1009 1010 tt_uint_op(sum, ==, evbuffer_get_length(buf)); 1011 1012 { 1013 size_t a,w,u; 1014 a=w=u=0; 1015 evbuffer_get_waste(buf, &a, &w, &u); 1016 if (0) 1017 printf("Allocated: %u.\nWasted: %u.\nUsed: %u.", 1018 (unsigned)a, (unsigned)w, (unsigned)u); 1019 tt_assert( ((double)w)/a < .125); 1020 } 1021 end: 1022 evbuffer_free(buf); 1023 1024 } 1025 1026 static void 1027 test_evbuffer_find(void *ptr) 1028 { 1029 u_char* p; 1030 const char* test1 = "1234567890\r\n"; 1031 const char* test2 = "1234567890\r"; 1032 #define EVBUFFER_INITIAL_LENGTH 256 1033 char test3[EVBUFFER_INITIAL_LENGTH]; 1034 unsigned int i; 1035 struct evbuffer * buf = evbuffer_new(); 1036 1037 tt_assert(buf); 1038 1039 /* make sure evbuffer_find doesn't match past the end of the buffer */ 1040 evbuffer_add(buf, __UNCONST(test1), strlen(test1)); 1041 evbuffer_validate(buf); 1042 evbuffer_drain(buf, strlen(test1)); 1043 evbuffer_validate(buf); 1044 evbuffer_add(buf, __UNCONST(test2), strlen(test2)); 1045 evbuffer_validate(buf); 1046 p = evbuffer_find(buf, __UNCONST("\r\n"), 2); 1047 tt_want(p == NULL); 1048 1049 /* 1050 * drain the buffer and do another find; in r309 this would 1051 * read past the allocated buffer causing a valgrind error. 1052 */ 1053 evbuffer_drain(buf, strlen(test2)); 1054 evbuffer_validate(buf); 1055 for (i = 0; i < EVBUFFER_INITIAL_LENGTH; ++i) 1056 test3[i] = 'a'; 1057 test3[EVBUFFER_INITIAL_LENGTH - 1] = 'x'; 1058 evbuffer_add(buf, (u_char *)test3, EVBUFFER_INITIAL_LENGTH); 1059 evbuffer_validate(buf); 1060 p = evbuffer_find(buf, __UNCONST("xy"), 2); 1061 tt_want(p == NULL); 1062 1063 /* simple test for match at end of allocated buffer */ 1064 p = evbuffer_find(buf, __UNCONST("ax"), 2); 1065 tt_assert(p != NULL); 1066 tt_want(strncmp((char*)p, "ax", 2) == 0); 1067 1068 end: 1069 if (buf) 1070 evbuffer_free(buf); 1071 } 1072 1073 static void 1074 test_evbuffer_ptr_set(void *ptr) 1075 { 1076 struct evbuffer *buf = evbuffer_new(); 1077 struct evbuffer_ptr pos; 1078 struct evbuffer_iovec v[1]; 1079 1080 tt_assert(buf); 1081 1082 /* create some chains */ 1083 evbuffer_reserve_space(buf, 5000, v, 1); 1084 v[0].iov_len = 5000; 1085 memset(v[0].iov_base, 1, v[0].iov_len); 1086 evbuffer_commit_space(buf, v, 1); 1087 evbuffer_validate(buf); 1088 1089 evbuffer_reserve_space(buf, 4000, v, 1); 1090 v[0].iov_len = 4000; 1091 memset(v[0].iov_base, 2, v[0].iov_len); 1092 evbuffer_commit_space(buf, v, 1); 1093 1094 evbuffer_reserve_space(buf, 3000, v, 1); 1095 v[0].iov_len = 3000; 1096 memset(v[0].iov_base, 3, v[0].iov_len); 1097 evbuffer_commit_space(buf, v, 1); 1098 evbuffer_validate(buf); 1099 1100 tt_int_op(evbuffer_get_length(buf), ==, 12000); 1101 1102 tt_assert(evbuffer_ptr_set(buf, &pos, 13000, EVBUFFER_PTR_SET) == -1); 1103 tt_assert(pos.pos == -1); 1104 tt_assert(evbuffer_ptr_set(buf, &pos, 0, EVBUFFER_PTR_SET) == 0); 1105 tt_assert(pos.pos == 0); 1106 tt_assert(evbuffer_ptr_set(buf, &pos, 13000, EVBUFFER_PTR_ADD) == -1); 1107 1108 tt_assert(evbuffer_ptr_set(buf, &pos, 0, EVBUFFER_PTR_SET) == 0); 1109 tt_assert(pos.pos == 0); 1110 tt_assert(evbuffer_ptr_set(buf, &pos, 10000, EVBUFFER_PTR_ADD) == 0); 1111 tt_assert(pos.pos == 10000); 1112 tt_assert(evbuffer_ptr_set(buf, &pos, 1000, EVBUFFER_PTR_ADD) == 0); 1113 tt_assert(pos.pos == 11000); 1114 tt_assert(evbuffer_ptr_set(buf, &pos, 1000, EVBUFFER_PTR_ADD) == -1); 1115 tt_assert(pos.pos == -1); 1116 1117 end: 1118 if (buf) 1119 evbuffer_free(buf); 1120 } 1121 1122 static void 1123 test_evbuffer_search(void *ptr) 1124 { 1125 struct evbuffer *buf = evbuffer_new(); 1126 struct evbuffer *tmp = evbuffer_new(); 1127 struct evbuffer_ptr pos, end; 1128 1129 tt_assert(buf); 1130 tt_assert(tmp); 1131 1132 /* set up our chains */ 1133 evbuffer_add_printf(tmp, "hello"); /* 5 chars */ 1134 evbuffer_add_buffer(buf, tmp); 1135 evbuffer_add_printf(tmp, "foo"); /* 3 chars */ 1136 evbuffer_add_buffer(buf, tmp); 1137 evbuffer_add_printf(tmp, "cat"); /* 3 chars */ 1138 evbuffer_add_buffer(buf, tmp); 1139 evbuffer_add_printf(tmp, "attack"); 1140 evbuffer_add_buffer(buf, tmp); 1141 1142 pos = evbuffer_search(buf, "attack", 6, NULL); 1143 tt_int_op(pos.pos, ==, 11); 1144 pos = evbuffer_search(buf, "attacker", 8, NULL); 1145 tt_int_op(pos.pos, ==, -1); 1146 1147 /* test continuing search */ 1148 pos = evbuffer_search(buf, "oc", 2, NULL); 1149 tt_int_op(pos.pos, ==, 7); 1150 pos = evbuffer_search(buf, "cat", 3, &pos); 1151 tt_int_op(pos.pos, ==, 8); 1152 pos = evbuffer_search(buf, "tacking", 7, &pos); 1153 tt_int_op(pos.pos, ==, -1); 1154 1155 evbuffer_ptr_set(buf, &pos, 5, EVBUFFER_PTR_SET); 1156 pos = evbuffer_search(buf, "foo", 3, &pos); 1157 tt_int_op(pos.pos, ==, 5); 1158 1159 evbuffer_ptr_set(buf, &pos, 2, EVBUFFER_PTR_ADD); 1160 pos = evbuffer_search(buf, "tat", 3, &pos); 1161 tt_int_op(pos.pos, ==, 10); 1162 1163 /* test bounded search. */ 1164 /* Set "end" to the first t in "attack". */ 1165 evbuffer_ptr_set(buf, &end, 12, EVBUFFER_PTR_SET); 1166 pos = evbuffer_search_range(buf, "foo", 3, NULL, &end); 1167 tt_int_op(pos.pos, ==, 5); 1168 pos = evbuffer_search_range(buf, "foocata", 7, NULL, &end); 1169 tt_int_op(pos.pos, ==, 5); 1170 pos = evbuffer_search_range(buf, "foocatat", 8, NULL, &end); 1171 tt_int_op(pos.pos, ==, -1); 1172 pos = evbuffer_search_range(buf, "ack", 3, NULL, &end); 1173 tt_int_op(pos.pos, ==, -1); 1174 1175 1176 end: 1177 if (buf) 1178 evbuffer_free(buf); 1179 if (tmp) 1180 evbuffer_free(tmp); 1181 } 1182 1183 static void 1184 log_change_callback(struct evbuffer *buffer, 1185 const struct evbuffer_cb_info *cbinfo, 1186 void *arg) 1187 { 1188 1189 size_t old_len = cbinfo->orig_size; 1190 size_t new_len = old_len + cbinfo->n_added - cbinfo->n_deleted; 1191 struct evbuffer *out = arg; 1192 evbuffer_add_printf(out, "%lu->%lu; ", (unsigned long)old_len, 1193 (unsigned long)new_len); 1194 } 1195 static void 1196 self_draining_callback(struct evbuffer *evbuffer, size_t old_len, 1197 size_t new_len, void *arg) 1198 { 1199 if (new_len > old_len) 1200 evbuffer_drain(evbuffer, new_len); 1201 } 1202 1203 static void 1204 test_evbuffer_callbacks(void *ptr) 1205 { 1206 struct evbuffer *buf = evbuffer_new(); 1207 struct evbuffer *buf_out1 = evbuffer_new(); 1208 struct evbuffer *buf_out2 = evbuffer_new(); 1209 struct evbuffer_cb_entry *cb1, *cb2; 1210 1211 tt_assert(buf); 1212 tt_assert(buf_out1); 1213 tt_assert(buf_out2); 1214 1215 cb1 = evbuffer_add_cb(buf, log_change_callback, buf_out1); 1216 cb2 = evbuffer_add_cb(buf, log_change_callback, buf_out2); 1217 1218 /* Let's run through adding and deleting some stuff from the buffer 1219 * and turning the callbacks on and off and removing them. The callback 1220 * adds a summary of length changes to buf_out1/buf_out2 when called. */ 1221 /* size: 0-> 36. */ 1222 evbuffer_add_printf(buf, "The %d magic words are spotty pudding", 2); 1223 evbuffer_validate(buf); 1224 evbuffer_cb_clear_flags(buf, cb2, EVBUFFER_CB_ENABLED); 1225 evbuffer_drain(buf, 10); /*36->26*/ 1226 evbuffer_validate(buf); 1227 evbuffer_prepend(buf, "Hello", 5);/*26->31*/ 1228 evbuffer_cb_set_flags(buf, cb2, EVBUFFER_CB_ENABLED); 1229 evbuffer_add_reference(buf, "Goodbye", 7, NULL, NULL); /*31->38*/ 1230 evbuffer_remove_cb_entry(buf, cb1); 1231 evbuffer_validate(buf); 1232 evbuffer_drain(buf, evbuffer_get_length(buf)); /*38->0*/; 1233 tt_assert(-1 == evbuffer_remove_cb(buf, log_change_callback, NULL)); 1234 evbuffer_add(buf, "X", 1); /* 0->1 */ 1235 tt_assert(!evbuffer_remove_cb(buf, log_change_callback, buf_out2)); 1236 evbuffer_validate(buf); 1237 1238 tt_str_op(evbuffer_pullup(buf_out1, -1), ==, 1239 "0->36; 36->26; 26->31; 31->38; "); 1240 tt_str_op(evbuffer_pullup(buf_out2, -1), ==, 1241 "0->36; 31->38; 38->0; 0->1; "); 1242 evbuffer_drain(buf_out1, evbuffer_get_length(buf_out1)); 1243 evbuffer_drain(buf_out2, evbuffer_get_length(buf_out2)); 1244 /* Let's test the obsolete buffer_setcb function too. */ 1245 cb1 = evbuffer_add_cb(buf, log_change_callback, buf_out1); 1246 tt_assert(cb1 != NULL); 1247 cb2 = evbuffer_add_cb(buf, log_change_callback, buf_out2); 1248 tt_assert(cb2 != NULL); 1249 evbuffer_setcb(buf, self_draining_callback, NULL); 1250 evbuffer_add_printf(buf, "This should get drained right away."); 1251 tt_uint_op(evbuffer_get_length(buf), ==, 0); 1252 tt_uint_op(evbuffer_get_length(buf_out1), ==, 0); 1253 tt_uint_op(evbuffer_get_length(buf_out2), ==, 0); 1254 evbuffer_setcb(buf, NULL, NULL); 1255 evbuffer_add_printf(buf, "This will not."); 1256 tt_str_op(evbuffer_pullup(buf, -1), ==, "This will not."); 1257 evbuffer_validate(buf); 1258 evbuffer_drain(buf, evbuffer_get_length(buf)); 1259 evbuffer_validate(buf); 1260 #if 0 1261 /* Now let's try a suspended callback. */ 1262 cb1 = evbuffer_add_cb(buf, log_change_callback, buf_out1); 1263 cb2 = evbuffer_add_cb(buf, log_change_callback, buf_out2); 1264 evbuffer_cb_suspend(buf,cb2); 1265 evbuffer_prepend(buf,"Hello world",11); /*0->11*/ 1266 evbuffer_validate(buf); 1267 evbuffer_cb_suspend(buf,cb1); 1268 evbuffer_add(buf,"more",4); /* 11->15 */ 1269 evbuffer_cb_unsuspend(buf,cb2); 1270 evbuffer_drain(buf, 4); /* 15->11 */ 1271 evbuffer_cb_unsuspend(buf,cb1); 1272 evbuffer_drain(buf, evbuffer_get_length(buf)); /* 11->0 */ 1273 1274 tt_str_op(evbuffer_pullup(buf_out1, -1), ==, 1275 "0->11; 11->11; 11->0; "); 1276 tt_str_op(evbuffer_pullup(buf_out2, -1), ==, 1277 "0->15; 15->11; 11->0; "); 1278 #endif 1279 1280 end: 1281 if (buf) 1282 evbuffer_free(buf); 1283 if (buf_out1) 1284 evbuffer_free(buf_out1); 1285 if (buf_out2) 1286 evbuffer_free(buf_out2); 1287 } 1288 1289 static int ref_done_cb_called_count = 0; 1290 static void *ref_done_cb_called_with = NULL; 1291 static const void *ref_done_cb_called_with_data = NULL; 1292 static size_t ref_done_cb_called_with_len = 0; 1293 static void ref_done_cb(const void *data, size_t len, void *info) 1294 { 1295 ++ref_done_cb_called_count; 1296 ref_done_cb_called_with = info; 1297 ref_done_cb_called_with_data = data; 1298 ref_done_cb_called_with_len = len; 1299 } 1300 1301 static void 1302 test_evbuffer_add_reference(void *ptr) 1303 { 1304 const char chunk1[] = "If you have found the answer to such a problem"; 1305 const char chunk2[] = "you ought to write it up for publication"; 1306 /* -- Knuth's "Notes on the Exercises" from TAOCP */ 1307 char tmp[16]; 1308 size_t len1 = strlen(chunk1), len2=strlen(chunk2); 1309 1310 struct evbuffer *buf1 = NULL, *buf2 = NULL; 1311 1312 buf1 = evbuffer_new(); 1313 tt_assert(buf1); 1314 1315 evbuffer_add_reference(buf1, chunk1, len1, ref_done_cb, (void*)111); 1316 evbuffer_add(buf1, ", ", 2); 1317 evbuffer_add_reference(buf1, chunk2, len2, ref_done_cb, (void*)222); 1318 tt_int_op(evbuffer_get_length(buf1), ==, len1+len2+2); 1319 1320 /* Make sure we can drain a little from a reference. */ 1321 tt_int_op(evbuffer_remove(buf1, tmp, 6), ==, 6); 1322 tt_int_op(memcmp(tmp, "If you", 6), ==, 0); 1323 tt_int_op(evbuffer_remove(buf1, tmp, 5), ==, 5); 1324 tt_int_op(memcmp(tmp, " have", 5), ==, 0); 1325 1326 /* Make sure that prepending does not meddle with immutable data */ 1327 tt_int_op(evbuffer_prepend(buf1, "I have ", 7), ==, 0); 1328 tt_int_op(memcmp(chunk1, "If you", 6), ==, 0); 1329 evbuffer_validate(buf1); 1330 1331 /* Make sure that when the chunk is over, the callback is invoked. */ 1332 evbuffer_drain(buf1, 7); /* Remove prepended stuff. */ 1333 evbuffer_drain(buf1, len1-11-1); /* remove all but one byte of chunk1 */ 1334 tt_int_op(ref_done_cb_called_count, ==, 0); 1335 evbuffer_remove(buf1, tmp, 1); 1336 tt_int_op(tmp[0], ==, 'm'); 1337 tt_assert(ref_done_cb_called_with == (void*)111); 1338 tt_assert(ref_done_cb_called_with_data == chunk1); 1339 tt_assert(ref_done_cb_called_with_len == len1); 1340 tt_int_op(ref_done_cb_called_count, ==, 1); 1341 evbuffer_validate(buf1); 1342 1343 /* Drain some of the remaining chunk, then add it to another buffer */ 1344 evbuffer_drain(buf1, 6); /* Remove the ", you ". */ 1345 buf2 = evbuffer_new(); 1346 tt_assert(buf2); 1347 tt_int_op(ref_done_cb_called_count, ==, 1); 1348 evbuffer_add(buf2, "I ", 2); 1349 1350 evbuffer_add_buffer(buf2, buf1); 1351 tt_int_op(ref_done_cb_called_count, ==, 1); 1352 evbuffer_remove(buf2, tmp, 16); 1353 tt_int_op(memcmp("I ought to write", tmp, 16), ==, 0); 1354 evbuffer_drain(buf2, evbuffer_get_length(buf2)); 1355 tt_int_op(ref_done_cb_called_count, ==, 2); 1356 tt_assert(ref_done_cb_called_with == (void*)222); 1357 evbuffer_validate(buf2); 1358 1359 /* Now add more stuff to buf1 and make sure that it gets removed on 1360 * free. */ 1361 evbuffer_add(buf1, "You shake and shake the ", 24); 1362 evbuffer_add_reference(buf1, "ketchup bottle", 14, ref_done_cb, 1363 (void*)3333); 1364 evbuffer_add(buf1, ". Nothing comes and then a lot'll.", 42); 1365 evbuffer_free(buf1); 1366 buf1 = NULL; 1367 tt_int_op(ref_done_cb_called_count, ==, 3); 1368 tt_assert(ref_done_cb_called_with == (void*)3333); 1369 1370 end: 1371 if (buf1) 1372 evbuffer_free(buf1); 1373 if (buf2) 1374 evbuffer_free(buf2); 1375 } 1376 1377 /* Some cases that we didn't get in test_evbuffer() above, for more coverage. */ 1378 static void 1379 test_evbuffer_prepend(void *ptr) 1380 { 1381 struct evbuffer *buf1 = NULL, *buf2 = NULL; 1382 char tmp[128]; 1383 int n; 1384 1385 buf1 = evbuffer_new(); 1386 tt_assert(buf1); 1387 1388 /* Case 0: The evbuffer is entirely empty. */ 1389 evbuffer_prepend(buf1, "This string has 29 characters", 29); 1390 evbuffer_validate(buf1); 1391 1392 /* Case 1: Prepend goes entirely in new chunk. */ 1393 evbuffer_prepend(buf1, "Short.", 6); 1394 evbuffer_validate(buf1); 1395 1396 /* Case 2: prepend goes entirely in first chunk. */ 1397 evbuffer_drain(buf1, 6+11); 1398 evbuffer_prepend(buf1, "it", 2); 1399 evbuffer_validate(buf1); 1400 tt_assert(!memcmp(buf1->first->buffer+buf1->first->misalign, 1401 "it has", 6)); 1402 1403 /* Case 3: prepend is split over multiple chunks. */ 1404 evbuffer_prepend(buf1, "It is no longer true to say ", 28); 1405 evbuffer_validate(buf1); 1406 n = evbuffer_remove(buf1, tmp, sizeof(tmp)-1); 1407 tmp[n]='\0'; 1408 tt_str_op(tmp,==,"It is no longer true to say it has 29 characters"); 1409 1410 buf2 = evbuffer_new(); 1411 tt_assert(buf2); 1412 1413 /* Case 4: prepend a buffer to an empty buffer. */ 1414 n = 999; 1415 evbuffer_add_printf(buf1, "Here is string %d. ", n++); 1416 evbuffer_prepend_buffer(buf2, buf1); 1417 evbuffer_validate(buf2); 1418 1419 /* Case 5: prepend a buffer to a nonempty buffer. */ 1420 evbuffer_add_printf(buf1, "Here is string %d. ", n++); 1421 evbuffer_prepend_buffer(buf2, buf1); 1422 evbuffer_validate(buf2); 1423 evbuffer_validate(buf1); 1424 n = evbuffer_remove(buf2, tmp, sizeof(tmp)-1); 1425 tmp[n]='\0'; 1426 tt_str_op(tmp,==,"Here is string 1000. Here is string 999. "); 1427 1428 end: 1429 if (buf1) 1430 evbuffer_free(buf1); 1431 if (buf2) 1432 evbuffer_free(buf2); 1433 1434 } 1435 1436 static void 1437 test_evbuffer_peek(void *info) 1438 { 1439 struct evbuffer *buf = NULL, *tmp_buf = NULL; 1440 int i; 1441 struct evbuffer_iovec v[20]; 1442 struct evbuffer_ptr ptr; 1443 1444 #define tt_iov_eq(v, s) \ 1445 tt_int_op((v)->iov_len, ==, strlen(s)); \ 1446 tt_assert(!memcmp((v)->iov_base, (s), strlen(s))) 1447 1448 /* Let's make a very fragmented buffer. */ 1449 buf = evbuffer_new(); 1450 tmp_buf = evbuffer_new(); 1451 for (i = 0; i < 16; ++i) { 1452 evbuffer_add_printf(tmp_buf, "Contents of chunk [%d]\n", i); 1453 evbuffer_add_buffer(buf, tmp_buf); 1454 } 1455 1456 /* How many chunks do we need for everything? */ 1457 i = evbuffer_peek(buf, -1, NULL, NULL, 0); 1458 tt_int_op(i, ==, 16); 1459 1460 /* Simple peek: get everything. */ 1461 i = evbuffer_peek(buf, -1, NULL, v, 20); 1462 tt_int_op(i, ==, 16); /* we used only 16 chunks. */ 1463 tt_iov_eq(&v[0], "Contents of chunk [0]\n"); 1464 tt_iov_eq(&v[3], "Contents of chunk [3]\n"); 1465 tt_iov_eq(&v[12], "Contents of chunk [12]\n"); 1466 tt_iov_eq(&v[15], "Contents of chunk [15]\n"); 1467 1468 /* Just get one chunk worth. */ 1469 memset(v, 0, sizeof(v)); 1470 i = evbuffer_peek(buf, -1, NULL, v, 1); 1471 tt_int_op(i, ==, 1); 1472 tt_iov_eq(&v[0], "Contents of chunk [0]\n"); 1473 tt_assert(v[1].iov_base == NULL); 1474 1475 /* Suppose we want at least the first 40 bytes. */ 1476 memset(v, 0, sizeof(v)); 1477 i = evbuffer_peek(buf, 40, NULL, v, 16); 1478 tt_int_op(i, ==, 2); 1479 tt_iov_eq(&v[0], "Contents of chunk [0]\n"); 1480 tt_iov_eq(&v[1], "Contents of chunk [1]\n"); 1481 tt_assert(v[2].iov_base == NULL); 1482 1483 /* How many chunks do we need for 100 bytes? */ 1484 memset(v, 0, sizeof(v)); 1485 i = evbuffer_peek(buf, 100, NULL, NULL, 0); 1486 tt_int_op(i, ==, 5); 1487 tt_assert(v[0].iov_base == NULL); 1488 1489 /* Now we ask for more bytes than we provide chunks for */ 1490 memset(v, 0, sizeof(v)); 1491 i = evbuffer_peek(buf, 60, NULL, v, 1); 1492 tt_int_op(i, ==, 3); 1493 tt_iov_eq(&v[0], "Contents of chunk [0]\n"); 1494 tt_assert(v[1].iov_base == NULL); 1495 1496 /* Now we ask for more bytes than the buffer has. */ 1497 memset(v, 0, sizeof(v)); 1498 i = evbuffer_peek(buf, 65536, NULL, v, 20); 1499 tt_int_op(i, ==, 16); /* we used only 16 chunks. */ 1500 tt_iov_eq(&v[0], "Contents of chunk [0]\n"); 1501 tt_iov_eq(&v[3], "Contents of chunk [3]\n"); 1502 tt_iov_eq(&v[12], "Contents of chunk [12]\n"); 1503 tt_iov_eq(&v[15], "Contents of chunk [15]\n"); 1504 tt_assert(v[16].iov_base == NULL); 1505 1506 /* What happens if we try an empty buffer? */ 1507 memset(v, 0, sizeof(v)); 1508 i = evbuffer_peek(tmp_buf, -1, NULL, v, 20); 1509 tt_int_op(i, ==, 0); 1510 tt_assert(v[0].iov_base == NULL); 1511 memset(v, 0, sizeof(v)); 1512 i = evbuffer_peek(tmp_buf, 50, NULL, v, 20); 1513 tt_int_op(i, ==, 0); 1514 tt_assert(v[0].iov_base == NULL); 1515 1516 /* Okay, now time to have fun with pointers. */ 1517 memset(v, 0, sizeof(v)); 1518 evbuffer_ptr_set(buf, &ptr, 30, EVBUFFER_PTR_SET); 1519 i = evbuffer_peek(buf, 50, &ptr, v, 20); 1520 tt_int_op(i, ==, 3); 1521 tt_iov_eq(&v[0], " of chunk [1]\n"); 1522 tt_iov_eq(&v[1], "Contents of chunk [2]\n"); 1523 tt_iov_eq(&v[2], "Contents of chunk [3]\n"); /*more than we asked for*/ 1524 1525 /* advance to the start of another chain. */ 1526 memset(v, 0, sizeof(v)); 1527 evbuffer_ptr_set(buf, &ptr, 14, EVBUFFER_PTR_ADD); 1528 i = evbuffer_peek(buf, 44, &ptr, v, 20); 1529 tt_int_op(i, ==, 2); 1530 tt_iov_eq(&v[0], "Contents of chunk [2]\n"); 1531 tt_iov_eq(&v[1], "Contents of chunk [3]\n"); /*more than we asked for*/ 1532 1533 end: 1534 if (buf) 1535 evbuffer_free(buf); 1536 if (tmp_buf) 1537 evbuffer_free(tmp_buf); 1538 } 1539 1540 /* Check whether evbuffer freezing works right. This is called twice, 1541 once with the argument "start" and once with the argument "end". 1542 When we test "start", we freeze the start of an evbuffer and make sure 1543 that modifying the start of the buffer doesn't work. When we test 1544 "end", we freeze the end of an evbuffer and make sure that modifying 1545 the end of the buffer doesn't work. 1546 */ 1547 static void 1548 test_evbuffer_freeze(void *ptr) 1549 { 1550 struct evbuffer *buf = NULL, *tmp_buf=NULL; 1551 const char string[] = /* Year's End, Richard Wilbur */ 1552 "I've known the wind by water banks to shake\n" 1553 "The late leaves down, which frozen where they fell\n" 1554 "And held in ice as dancers in a spell\n" 1555 "Fluttered all winter long into a lake..."; 1556 const int start = !strcmp(ptr, "start"); 1557 char *cp; 1558 char charbuf[128]; 1559 int r; 1560 size_t orig_length; 1561 struct evbuffer_iovec v[1]; 1562 1563 if (!start) 1564 tt_str_op(ptr, ==, "end"); 1565 1566 buf = evbuffer_new(); 1567 tmp_buf = evbuffer_new(); 1568 tt_assert(tmp_buf); 1569 1570 evbuffer_add(buf, string, strlen(string)); 1571 evbuffer_freeze(buf, start); /* Freeze the start or the end.*/ 1572 1573 #define FREEZE_EQ(a, startcase, endcase) \ 1574 do { \ 1575 if (start) { \ 1576 tt_int_op((a), ==, (startcase)); \ 1577 } else { \ 1578 tt_int_op((a), ==, (endcase)); \ 1579 } \ 1580 } while (/*CONSTCOND*/0) 1581 1582 1583 orig_length = evbuffer_get_length(buf); 1584 1585 /* These functions all manipulate the end of buf. */ 1586 r = evbuffer_add(buf, "abc", 0); 1587 FREEZE_EQ(r, 0, -1); 1588 r = evbuffer_reserve_space(buf, 10, v, 1); 1589 FREEZE_EQ(r, 1, -1); 1590 if (r == 0) { 1591 memset(v[0].iov_base, 'X', 10); 1592 v[0].iov_len = 10; 1593 } 1594 r = evbuffer_commit_space(buf, v, 1); 1595 FREEZE_EQ(r, 0, -1); 1596 r = evbuffer_add_reference(buf, string, 5, NULL, NULL); 1597 FREEZE_EQ(r, 0, -1); 1598 r = evbuffer_add_printf(buf, "Hello %s", "world"); 1599 FREEZE_EQ(r, 11, -1); 1600 /* TODO: test add_buffer, add_file, read */ 1601 1602 if (!start) 1603 tt_int_op(orig_length, ==, evbuffer_get_length(buf)); 1604 1605 orig_length = evbuffer_get_length(buf); 1606 1607 /* These functions all manipulate the start of buf. */ 1608 r = evbuffer_remove(buf, charbuf, 1); 1609 FREEZE_EQ(r, -1, 1); 1610 r = evbuffer_drain(buf, 3); 1611 FREEZE_EQ(r, -1, 0); 1612 r = evbuffer_prepend(buf, "dummy", 5); 1613 FREEZE_EQ(r, -1, 0); 1614 cp = evbuffer_readln(buf, NULL, EVBUFFER_EOL_LF); 1615 FREEZE_EQ(cp==NULL, 1, 0); 1616 if (cp) 1617 free(cp); 1618 /* TODO: Test remove_buffer, add_buffer, write, prepend_buffer */ 1619 1620 if (start) 1621 tt_int_op(orig_length, ==, evbuffer_get_length(buf)); 1622 1623 end: 1624 if (buf) 1625 evbuffer_free(buf); 1626 1627 if (tmp_buf) 1628 evbuffer_free(tmp_buf); 1629 } 1630 1631 static void * 1632 setup_passthrough(const struct testcase_t *testcase) 1633 { 1634 return testcase->setup_data; 1635 } 1636 static int 1637 cleanup_passthrough(const struct testcase_t *testcase, void *ptr) 1638 { 1639 (void) ptr; 1640 return 1; 1641 } 1642 1643 static const struct testcase_setup_t nil_setup = { 1644 setup_passthrough, 1645 cleanup_passthrough 1646 }; 1647 1648 struct testcase_t evbuffer_testcases[] = { 1649 { "evbuffer", test_evbuffer, 0, NULL, NULL }, 1650 { "remove_buffer_with_empty", test_evbuffer_remove_buffer_with_empty, 0, NULL, NULL }, 1651 { "reserve2", test_evbuffer_reserve2, 0, NULL, NULL }, 1652 { "reserve_many", test_evbuffer_reserve_many, 0, NULL, NULL }, 1653 { "reserve_many2", test_evbuffer_reserve_many, 0, &nil_setup, __UNCONST("add") }, 1654 { "reserve_many3", test_evbuffer_reserve_many, 0, &nil_setup, __UNCONST("fill") }, 1655 { "expand", test_evbuffer_expand, 0, NULL, NULL }, 1656 { "reference", test_evbuffer_reference, 0, NULL, NULL }, 1657 { "iterative", test_evbuffer_iterative, 0, NULL, NULL }, 1658 { "readln", test_evbuffer_readln, TT_NO_LOGS, &basic_setup, NULL }, 1659 { "search_eol", test_evbuffer_search_eol, 0, NULL, NULL }, 1660 { "find", test_evbuffer_find, 0, NULL, NULL }, 1661 { "ptr_set", test_evbuffer_ptr_set, 0, NULL, NULL }, 1662 { "search", test_evbuffer_search, 0, NULL, NULL }, 1663 { "callbacks", test_evbuffer_callbacks, 0, NULL, NULL }, 1664 { "add_reference", test_evbuffer_add_reference, 0, NULL, NULL }, 1665 { "prepend", test_evbuffer_prepend, TT_FORK, NULL, NULL }, 1666 { "peek", test_evbuffer_peek, 0, NULL, NULL }, 1667 { "freeze_start", test_evbuffer_freeze, 0, &nil_setup, __UNCONST("start") }, 1668 { "freeze_end", test_evbuffer_freeze, 0, &nil_setup, __UNCONST("end") }, 1669 /* TODO: need a temp file implementation for Windows */ 1670 { "add_file_sendfile", test_evbuffer_add_file, TT_FORK, &nil_setup, 1671 __UNCONST("sendfile") }, 1672 { "add_file_mmap", test_evbuffer_add_file, TT_FORK, &nil_setup, 1673 __UNCONST("mmap") }, 1674 { "add_file_linear", test_evbuffer_add_file, TT_FORK, &nil_setup, 1675 __UNCONST("linear") }, 1676 1677 END_OF_TESTCASES 1678 }; 1679