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