root/opal/mca/event/libevent2022/libevent/test/regress_iocp.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. count_init
  2. count_free
  3. count_incr
  4. count_wait_for
  5. dummy_cb
  6. pair_is_in
  7. test_iocp_port
  8. read_complete
  9. write_complete
  10. test_iocp_evbuffer
  11. async_readcb
  12. test_iocp_bufferevent_async

   1 /*
   2  * Copyright (c) 2009-2012 Niels Provos and Nick Mathewson
   3  *
   4  * Redistribution and use in source and binary forms, with or without
   5  * modification, are permitted provided that the following conditions
   6  * are met:
   7  * 1. Redistributions of source code must retain the above copyright
   8  *    notice, this list of conditions and the following disclaimer.
   9  * 2. Redistributions in binary form must reproduce the above copyright
  10  *    notice, this list of conditions and the following disclaimer in the
  11  *    documentation and/or other materials provided with the distribution.
  12  * 3. The name of the author may not be used to endorse or promote products
  13  *    derived from this software without specific prior written permission.
  14  *
  15  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
  16  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
  17  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
  18  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
  19  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
  20  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  21  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  22  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  23  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
  24  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  25  */
  26 
  27 #include <stdlib.h>
  28 #include <string.h>
  29 #include "event2/event.h"
  30 #include "event2/thread.h"
  31 #include "event2/buffer.h"
  32 #include "event2/buffer_compat.h"
  33 #include "event2/bufferevent.h"
  34 
  35 #include <winsock2.h>
  36 #include <ws2tcpip.h>
  37 
  38 #include "regress.h"
  39 #include "tinytest.h"
  40 #include "tinytest_macros.h"
  41 
  42 #define WIN32_LEAN_AND_MEAN
  43 #include <windows.h>
  44 #include <winsock2.h>
  45 #undef WIN32_LEAN_AND_MEAN
  46 
  47 #include "iocp-internal.h"
  48 #include "evbuffer-internal.h"
  49 #include "evthread-internal.h"
  50 
  51 /* FIXME remove these ones */
  52 #include <sys/queue.h>
  53 #include "event2/event_struct.h"
  54 #include "event-internal.h"
  55 
  56 #define MAX_CALLS 16
  57 
  58 static void *count_lock = NULL, *count_cond = NULL;
  59 static int count = 0;
  60 
  61 static void
  62 count_init(void)
  63 {
  64         EVTHREAD_ALLOC_LOCK(count_lock, 0);
  65         EVTHREAD_ALLOC_COND(count_cond);
  66 
  67         tt_assert(count_lock);
  68         tt_assert(count_cond);
  69 
  70 end:
  71         ;
  72 }
  73 
  74 static void
  75 count_free(void)
  76 {
  77         EVTHREAD_FREE_LOCK(count_lock, 0);
  78         EVTHREAD_FREE_COND(count_cond);
  79 }
  80 
  81 static void
  82 count_incr(void)
  83 {
  84         EVLOCK_LOCK(count_lock, 0);
  85         count++;
  86         EVTHREAD_COND_BROADCAST(count_cond);
  87         EVLOCK_UNLOCK(count_lock, 0);
  88 }
  89 
  90 static int
  91 count_wait_for(int i, int ms)
  92 {
  93         struct timeval tv;
  94         DWORD elapsed;
  95         int rv = -1;
  96 
  97         EVLOCK_LOCK(count_lock, 0);
  98         while (ms > 0 && count != i) {
  99                 tv.tv_sec = 0;
 100                 tv.tv_usec = ms * 1000;
 101                 elapsed = GetTickCount();
 102                 EVTHREAD_COND_WAIT_TIMED(count_cond, count_lock, &tv);
 103                 elapsed = GetTickCount() - elapsed;
 104                 ms -= elapsed;
 105         }
 106         if (count == i)
 107                 rv = 0;
 108         EVLOCK_UNLOCK(count_lock, 0);
 109 
 110         return rv;
 111 }
 112 
 113 struct dummy_overlapped {
 114         struct event_overlapped eo;
 115         void *lock;
 116         int call_count;
 117         uintptr_t keys[MAX_CALLS];
 118         ev_ssize_t sizes[MAX_CALLS];
 119 };
 120 
 121 static void
 122 dummy_cb(struct event_overlapped *o, uintptr_t key, ev_ssize_t n, int ok)
 123 {
 124         struct dummy_overlapped *d_o =
 125             EVUTIL_UPCAST(o, struct dummy_overlapped, eo);
 126 
 127         EVLOCK_LOCK(d_o->lock, 0);
 128         if (d_o->call_count < MAX_CALLS) {
 129                 d_o->keys[d_o->call_count] = key;
 130                 d_o->sizes[d_o->call_count] = n;
 131         }
 132         d_o->call_count++;
 133         EVLOCK_UNLOCK(d_o->lock, 0);
 134 
 135         count_incr();
 136 }
 137 
 138 static int
 139 pair_is_in(struct dummy_overlapped *o, uintptr_t key, ev_ssize_t n)
 140 {
 141         int i;
 142         int result = 0;
 143         EVLOCK_LOCK(o->lock, 0);
 144         for (i=0; i < o->call_count; ++i) {
 145                 if (o->keys[i] == key && o->sizes[i] == n) {
 146                         result = 1;
 147                         break;
 148                 }
 149         }
 150         EVLOCK_UNLOCK(o->lock, 0);
 151         return result;
 152 }
 153 
 154 static void
 155 test_iocp_port(void *ptr)
 156 {
 157         struct event_iocp_port *port = NULL;
 158         struct dummy_overlapped o1, o2;
 159 
 160         memset(&o1, 0, sizeof(o1));
 161         memset(&o2, 0, sizeof(o2));
 162 
 163         count_init();
 164         EVTHREAD_ALLOC_LOCK(o1.lock, EVTHREAD_LOCKTYPE_RECURSIVE);
 165         EVTHREAD_ALLOC_LOCK(o2.lock, EVTHREAD_LOCKTYPE_RECURSIVE);
 166 
 167         tt_assert(o1.lock);
 168         tt_assert(o2.lock);
 169 
 170         event_overlapped_init(&o1.eo, dummy_cb);
 171         event_overlapped_init(&o2.eo, dummy_cb);
 172 
 173         port = event_iocp_port_launch(0);
 174         tt_assert(port);
 175 
 176         tt_assert(!event_iocp_activate_overlapped(port, &o1.eo, 10, 100));
 177         tt_assert(!event_iocp_activate_overlapped(port, &o2.eo, 20, 200));
 178 
 179         tt_assert(!event_iocp_activate_overlapped(port, &o1.eo, 11, 101));
 180         tt_assert(!event_iocp_activate_overlapped(port, &o2.eo, 21, 201));
 181 
 182         tt_assert(!event_iocp_activate_overlapped(port, &o1.eo, 12, 102));
 183         tt_assert(!event_iocp_activate_overlapped(port, &o2.eo, 22, 202));
 184 
 185         tt_assert(!event_iocp_activate_overlapped(port, &o1.eo, 13, 103));
 186         tt_assert(!event_iocp_activate_overlapped(port, &o2.eo, 23, 203));
 187 
 188         tt_int_op(count_wait_for(8, 2000), ==, 0);
 189 
 190         tt_want(!event_iocp_shutdown(port, 2000));
 191 
 192         tt_int_op(o1.call_count, ==, 4);
 193         tt_int_op(o2.call_count, ==, 4);
 194 
 195         tt_want(pair_is_in(&o1, 10, 100));
 196         tt_want(pair_is_in(&o1, 11, 101));
 197         tt_want(pair_is_in(&o1, 12, 102));
 198         tt_want(pair_is_in(&o1, 13, 103));
 199 
 200         tt_want(pair_is_in(&o2, 20, 200));
 201         tt_want(pair_is_in(&o2, 21, 201));
 202         tt_want(pair_is_in(&o2, 22, 202));
 203         tt_want(pair_is_in(&o2, 23, 203));
 204 
 205 end:
 206         EVTHREAD_FREE_LOCK(o1.lock, EVTHREAD_LOCKTYPE_RECURSIVE);
 207         EVTHREAD_FREE_LOCK(o2.lock, EVTHREAD_LOCKTYPE_RECURSIVE);
 208         count_free();
 209 }
 210 
 211 static struct evbuffer *rbuf = NULL, *wbuf = NULL;
 212 
 213 static void
 214 read_complete(struct event_overlapped *eo, uintptr_t key,
 215     ev_ssize_t nbytes, int ok)
 216 {
 217         tt_assert(ok);
 218         evbuffer_commit_read(rbuf, nbytes);
 219         count_incr();
 220 end:
 221         ;
 222 }
 223 
 224 static void
 225 write_complete(struct event_overlapped *eo, uintptr_t key,
 226     ev_ssize_t nbytes, int ok)
 227 {
 228         tt_assert(ok);
 229         evbuffer_commit_write(wbuf, nbytes);
 230         count_incr();
 231 end:
 232         ;
 233 }
 234 
 235 static void
 236 test_iocp_evbuffer(void *ptr)
 237 {
 238         struct event_overlapped rol, wol;
 239         struct basic_test_data *data = ptr;
 240         struct event_iocp_port *port = NULL;
 241         struct evbuffer *buf=NULL;
 242         struct evbuffer_chain *chain;
 243         char junk[1024];
 244         int i;
 245 
 246         count_init();
 247         event_overlapped_init(&rol, read_complete);
 248         event_overlapped_init(&wol, write_complete);
 249 
 250         for (i = 0; i < (int)sizeof(junk); ++i)
 251                 junk[i] = (char)(i);
 252 
 253         rbuf = evbuffer_overlapped_new(data->pair[0]);
 254         wbuf = evbuffer_overlapped_new(data->pair[1]);
 255         evbuffer_enable_locking(rbuf, NULL);
 256         evbuffer_enable_locking(wbuf, NULL);
 257 
 258         port = event_iocp_port_launch(0);
 259         tt_assert(port);
 260         tt_assert(rbuf);
 261         tt_assert(wbuf);
 262 
 263         tt_assert(!event_iocp_port_associate(port, data->pair[0], 100));
 264         tt_assert(!event_iocp_port_associate(port, data->pair[1], 100));
 265 
 266         for (i=0;i<10;++i)
 267                 evbuffer_add(wbuf, junk, sizeof(junk));
 268 
 269         buf = evbuffer_new();
 270         tt_assert(buf != NULL);
 271         evbuffer_add(rbuf, junk, sizeof(junk));
 272         tt_assert(!evbuffer_launch_read(rbuf, 2048, &rol));
 273         evbuffer_add_buffer(buf, rbuf);
 274         tt_int_op(evbuffer_get_length(buf), ==, sizeof(junk));
 275         for (chain = buf->first; chain; chain = chain->next)
 276                 tt_int_op(chain->flags & EVBUFFER_MEM_PINNED_ANY, ==, 0);
 277         tt_assert(!evbuffer_get_length(rbuf));
 278         tt_assert(!evbuffer_launch_write(wbuf, 512, &wol));
 279 
 280         tt_int_op(count_wait_for(2, 2000), ==, 0);
 281 
 282         tt_int_op(evbuffer_get_length(rbuf),==,512);
 283 
 284         /* FIXME Actually test some stuff here. */
 285 
 286         tt_want(!event_iocp_shutdown(port, 2000));
 287 end:
 288         count_free();
 289         evbuffer_free(rbuf);
 290         evbuffer_free(wbuf);
 291         if (buf) evbuffer_free(buf);
 292 }
 293 
 294 static int got_readcb = 0;
 295 
 296 static void
 297 async_readcb(struct bufferevent *bev, void *arg)
 298 {
 299         /* Disabling read should cause the loop to quit */
 300         bufferevent_disable(bev, EV_READ);
 301         got_readcb++;
 302 }
 303 
 304 static void
 305 test_iocp_bufferevent_async(void *ptr)
 306 {
 307         struct basic_test_data *data = ptr;
 308         struct event_iocp_port *port = NULL;
 309         struct bufferevent *bea1=NULL, *bea2=NULL;
 310         char buf[128];
 311         size_t n;
 312 
 313         event_base_start_iocp(data->base, 0);
 314         port = event_base_get_iocp(data->base);
 315         tt_assert(port);
 316 
 317         bea1 = bufferevent_async_new(data->base, data->pair[0],
 318             BEV_OPT_DEFER_CALLBACKS);
 319         bea2 = bufferevent_async_new(data->base, data->pair[1],
 320             BEV_OPT_DEFER_CALLBACKS);
 321         tt_assert(bea1);
 322         tt_assert(bea2);
 323 
 324         bufferevent_setcb(bea2, async_readcb, NULL, NULL, NULL);
 325         bufferevent_enable(bea1, EV_WRITE);
 326         bufferevent_enable(bea2, EV_READ);
 327 
 328         bufferevent_write(bea1, "Hello world", strlen("Hello world")+1);
 329 
 330         event_base_dispatch(data->base);
 331 
 332         tt_int_op(got_readcb, ==, 1);
 333         n = bufferevent_read(bea2, buf, sizeof(buf)-1);
 334         buf[n]='\0';
 335         tt_str_op(buf, ==, "Hello world");
 336 
 337 end:
 338         bufferevent_free(bea1);
 339         bufferevent_free(bea2);
 340 }
 341 
 342 
 343 struct testcase_t iocp_testcases[] = {
 344         { "port", test_iocp_port, TT_FORK|TT_NEED_THREADS, &basic_setup, NULL },
 345         { "evbuffer", test_iocp_evbuffer,
 346           TT_FORK|TT_NEED_SOCKETPAIR|TT_NEED_THREADS,
 347           &basic_setup, NULL },
 348         { "bufferevent_async", test_iocp_bufferevent_async,
 349           TT_FORK|TT_NEED_SOCKETPAIR|TT_NEED_THREADS|TT_NEED_BASE,
 350           &basic_setup, NULL },
 351         END_OF_TESTCASES
 352 };

/* [<][>][^][v][top][bottom][index][help] */