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