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