1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/ipc/chromium/src/third_party/libevent/test/regress_iocp.c Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,352 @@ 1.4 +/* 1.5 + * Copyright (c) 2009-2012 Niels Provos and Nick Mathewson 1.6 + * 1.7 + * Redistribution and use in source and binary forms, with or without 1.8 + * modification, are permitted provided that the following conditions 1.9 + * are met: 1.10 + * 1. Redistributions of source code must retain the above copyright 1.11 + * notice, this list of conditions and the following disclaimer. 1.12 + * 2. Redistributions in binary form must reproduce the above copyright 1.13 + * notice, this list of conditions and the following disclaimer in the 1.14 + * documentation and/or other materials provided with the distribution. 1.15 + * 3. The name of the author may not be used to endorse or promote products 1.16 + * derived from this software without specific prior written permission. 1.17 + * 1.18 + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 1.19 + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 1.20 + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 1.21 + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 1.22 + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 1.23 + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 1.24 + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 1.25 + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 1.26 + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 1.27 + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 1.28 + */ 1.29 + 1.30 +#include <stdlib.h> 1.31 +#include <string.h> 1.32 +#include "event2/event.h" 1.33 +#include "event2/thread.h" 1.34 +#include "event2/buffer.h" 1.35 +#include "event2/buffer_compat.h" 1.36 +#include "event2/bufferevent.h" 1.37 + 1.38 +#include <winsock2.h> 1.39 +#include <ws2tcpip.h> 1.40 + 1.41 +#include "regress.h" 1.42 +#include "tinytest.h" 1.43 +#include "tinytest_macros.h" 1.44 + 1.45 +#define WIN32_LEAN_AND_MEAN 1.46 +#include <windows.h> 1.47 +#include <winsock2.h> 1.48 +#undef WIN32_LEAN_AND_MEAN 1.49 + 1.50 +#include "iocp-internal.h" 1.51 +#include "evbuffer-internal.h" 1.52 +#include "evthread-internal.h" 1.53 + 1.54 +/* FIXME remove these ones */ 1.55 +#include <sys/queue.h> 1.56 +#include "event2/event_struct.h" 1.57 +#include "event-internal.h" 1.58 + 1.59 +#define MAX_CALLS 16 1.60 + 1.61 +static void *count_lock = NULL, *count_cond = NULL; 1.62 +static int count = 0; 1.63 + 1.64 +static void 1.65 +count_init(void) 1.66 +{ 1.67 + EVTHREAD_ALLOC_LOCK(count_lock, 0); 1.68 + EVTHREAD_ALLOC_COND(count_cond); 1.69 + 1.70 + tt_assert(count_lock); 1.71 + tt_assert(count_cond); 1.72 + 1.73 +end: 1.74 + ; 1.75 +} 1.76 + 1.77 +static void 1.78 +count_free(void) 1.79 +{ 1.80 + EVTHREAD_FREE_LOCK(count_lock, 0); 1.81 + EVTHREAD_FREE_COND(count_cond); 1.82 +} 1.83 + 1.84 +static void 1.85 +count_incr(void) 1.86 +{ 1.87 + EVLOCK_LOCK(count_lock, 0); 1.88 + count++; 1.89 + EVTHREAD_COND_BROADCAST(count_cond); 1.90 + EVLOCK_UNLOCK(count_lock, 0); 1.91 +} 1.92 + 1.93 +static int 1.94 +count_wait_for(int i, int ms) 1.95 +{ 1.96 + struct timeval tv; 1.97 + DWORD elapsed; 1.98 + int rv = -1; 1.99 + 1.100 + EVLOCK_LOCK(count_lock, 0); 1.101 + while (ms > 0 && count != i) { 1.102 + tv.tv_sec = 0; 1.103 + tv.tv_usec = ms * 1000; 1.104 + elapsed = GetTickCount(); 1.105 + EVTHREAD_COND_WAIT_TIMED(count_cond, count_lock, &tv); 1.106 + elapsed = GetTickCount() - elapsed; 1.107 + ms -= elapsed; 1.108 + } 1.109 + if (count == i) 1.110 + rv = 0; 1.111 + EVLOCK_UNLOCK(count_lock, 0); 1.112 + 1.113 + return rv; 1.114 +} 1.115 + 1.116 +struct dummy_overlapped { 1.117 + struct event_overlapped eo; 1.118 + void *lock; 1.119 + int call_count; 1.120 + uintptr_t keys[MAX_CALLS]; 1.121 + ev_ssize_t sizes[MAX_CALLS]; 1.122 +}; 1.123 + 1.124 +static void 1.125 +dummy_cb(struct event_overlapped *o, uintptr_t key, ev_ssize_t n, int ok) 1.126 +{ 1.127 + struct dummy_overlapped *d_o = 1.128 + EVUTIL_UPCAST(o, struct dummy_overlapped, eo); 1.129 + 1.130 + EVLOCK_LOCK(d_o->lock, 0); 1.131 + if (d_o->call_count < MAX_CALLS) { 1.132 + d_o->keys[d_o->call_count] = key; 1.133 + d_o->sizes[d_o->call_count] = n; 1.134 + } 1.135 + d_o->call_count++; 1.136 + EVLOCK_UNLOCK(d_o->lock, 0); 1.137 + 1.138 + count_incr(); 1.139 +} 1.140 + 1.141 +static int 1.142 +pair_is_in(struct dummy_overlapped *o, uintptr_t key, ev_ssize_t n) 1.143 +{ 1.144 + int i; 1.145 + int result = 0; 1.146 + EVLOCK_LOCK(o->lock, 0); 1.147 + for (i=0; i < o->call_count; ++i) { 1.148 + if (o->keys[i] == key && o->sizes[i] == n) { 1.149 + result = 1; 1.150 + break; 1.151 + } 1.152 + } 1.153 + EVLOCK_UNLOCK(o->lock, 0); 1.154 + return result; 1.155 +} 1.156 + 1.157 +static void 1.158 +test_iocp_port(void *ptr) 1.159 +{ 1.160 + struct event_iocp_port *port = NULL; 1.161 + struct dummy_overlapped o1, o2; 1.162 + 1.163 + memset(&o1, 0, sizeof(o1)); 1.164 + memset(&o2, 0, sizeof(o2)); 1.165 + 1.166 + count_init(); 1.167 + EVTHREAD_ALLOC_LOCK(o1.lock, EVTHREAD_LOCKTYPE_RECURSIVE); 1.168 + EVTHREAD_ALLOC_LOCK(o2.lock, EVTHREAD_LOCKTYPE_RECURSIVE); 1.169 + 1.170 + tt_assert(o1.lock); 1.171 + tt_assert(o2.lock); 1.172 + 1.173 + event_overlapped_init(&o1.eo, dummy_cb); 1.174 + event_overlapped_init(&o2.eo, dummy_cb); 1.175 + 1.176 + port = event_iocp_port_launch(0); 1.177 + tt_assert(port); 1.178 + 1.179 + tt_assert(!event_iocp_activate_overlapped(port, &o1.eo, 10, 100)); 1.180 + tt_assert(!event_iocp_activate_overlapped(port, &o2.eo, 20, 200)); 1.181 + 1.182 + tt_assert(!event_iocp_activate_overlapped(port, &o1.eo, 11, 101)); 1.183 + tt_assert(!event_iocp_activate_overlapped(port, &o2.eo, 21, 201)); 1.184 + 1.185 + tt_assert(!event_iocp_activate_overlapped(port, &o1.eo, 12, 102)); 1.186 + tt_assert(!event_iocp_activate_overlapped(port, &o2.eo, 22, 202)); 1.187 + 1.188 + tt_assert(!event_iocp_activate_overlapped(port, &o1.eo, 13, 103)); 1.189 + tt_assert(!event_iocp_activate_overlapped(port, &o2.eo, 23, 203)); 1.190 + 1.191 + tt_int_op(count_wait_for(8, 2000), ==, 0); 1.192 + 1.193 + tt_want(!event_iocp_shutdown(port, 2000)); 1.194 + 1.195 + tt_int_op(o1.call_count, ==, 4); 1.196 + tt_int_op(o2.call_count, ==, 4); 1.197 + 1.198 + tt_want(pair_is_in(&o1, 10, 100)); 1.199 + tt_want(pair_is_in(&o1, 11, 101)); 1.200 + tt_want(pair_is_in(&o1, 12, 102)); 1.201 + tt_want(pair_is_in(&o1, 13, 103)); 1.202 + 1.203 + tt_want(pair_is_in(&o2, 20, 200)); 1.204 + tt_want(pair_is_in(&o2, 21, 201)); 1.205 + tt_want(pair_is_in(&o2, 22, 202)); 1.206 + tt_want(pair_is_in(&o2, 23, 203)); 1.207 + 1.208 +end: 1.209 + EVTHREAD_FREE_LOCK(o1.lock, EVTHREAD_LOCKTYPE_RECURSIVE); 1.210 + EVTHREAD_FREE_LOCK(o2.lock, EVTHREAD_LOCKTYPE_RECURSIVE); 1.211 + count_free(); 1.212 +} 1.213 + 1.214 +static struct evbuffer *rbuf = NULL, *wbuf = NULL; 1.215 + 1.216 +static void 1.217 +read_complete(struct event_overlapped *eo, uintptr_t key, 1.218 + ev_ssize_t nbytes, int ok) 1.219 +{ 1.220 + tt_assert(ok); 1.221 + evbuffer_commit_read(rbuf, nbytes); 1.222 + count_incr(); 1.223 +end: 1.224 + ; 1.225 +} 1.226 + 1.227 +static void 1.228 +write_complete(struct event_overlapped *eo, uintptr_t key, 1.229 + ev_ssize_t nbytes, int ok) 1.230 +{ 1.231 + tt_assert(ok); 1.232 + evbuffer_commit_write(wbuf, nbytes); 1.233 + count_incr(); 1.234 +end: 1.235 + ; 1.236 +} 1.237 + 1.238 +static void 1.239 +test_iocp_evbuffer(void *ptr) 1.240 +{ 1.241 + struct event_overlapped rol, wol; 1.242 + struct basic_test_data *data = ptr; 1.243 + struct event_iocp_port *port = NULL; 1.244 + struct evbuffer *buf=NULL; 1.245 + struct evbuffer_chain *chain; 1.246 + char junk[1024]; 1.247 + int i; 1.248 + 1.249 + count_init(); 1.250 + event_overlapped_init(&rol, read_complete); 1.251 + event_overlapped_init(&wol, write_complete); 1.252 + 1.253 + for (i = 0; i < (int)sizeof(junk); ++i) 1.254 + junk[i] = (char)(i); 1.255 + 1.256 + rbuf = evbuffer_overlapped_new(data->pair[0]); 1.257 + wbuf = evbuffer_overlapped_new(data->pair[1]); 1.258 + evbuffer_enable_locking(rbuf, NULL); 1.259 + evbuffer_enable_locking(wbuf, NULL); 1.260 + 1.261 + port = event_iocp_port_launch(0); 1.262 + tt_assert(port); 1.263 + tt_assert(rbuf); 1.264 + tt_assert(wbuf); 1.265 + 1.266 + tt_assert(!event_iocp_port_associate(port, data->pair[0], 100)); 1.267 + tt_assert(!event_iocp_port_associate(port, data->pair[1], 100)); 1.268 + 1.269 + for (i=0;i<10;++i) 1.270 + evbuffer_add(wbuf, junk, sizeof(junk)); 1.271 + 1.272 + buf = evbuffer_new(); 1.273 + tt_assert(buf != NULL); 1.274 + evbuffer_add(rbuf, junk, sizeof(junk)); 1.275 + tt_assert(!evbuffer_launch_read(rbuf, 2048, &rol)); 1.276 + evbuffer_add_buffer(buf, rbuf); 1.277 + tt_int_op(evbuffer_get_length(buf), ==, sizeof(junk)); 1.278 + for (chain = buf->first; chain; chain = chain->next) 1.279 + tt_int_op(chain->flags & EVBUFFER_MEM_PINNED_ANY, ==, 0); 1.280 + tt_assert(!evbuffer_get_length(rbuf)); 1.281 + tt_assert(!evbuffer_launch_write(wbuf, 512, &wol)); 1.282 + 1.283 + tt_int_op(count_wait_for(2, 2000), ==, 0); 1.284 + 1.285 + tt_int_op(evbuffer_get_length(rbuf),==,512); 1.286 + 1.287 + /* FIXME Actually test some stuff here. */ 1.288 + 1.289 + tt_want(!event_iocp_shutdown(port, 2000)); 1.290 +end: 1.291 + count_free(); 1.292 + evbuffer_free(rbuf); 1.293 + evbuffer_free(wbuf); 1.294 + if (buf) evbuffer_free(buf); 1.295 +} 1.296 + 1.297 +static int got_readcb = 0; 1.298 + 1.299 +static void 1.300 +async_readcb(struct bufferevent *bev, void *arg) 1.301 +{ 1.302 + /* Disabling read should cause the loop to quit */ 1.303 + bufferevent_disable(bev, EV_READ); 1.304 + got_readcb++; 1.305 +} 1.306 + 1.307 +static void 1.308 +test_iocp_bufferevent_async(void *ptr) 1.309 +{ 1.310 + struct basic_test_data *data = ptr; 1.311 + struct event_iocp_port *port = NULL; 1.312 + struct bufferevent *bea1=NULL, *bea2=NULL; 1.313 + char buf[128]; 1.314 + size_t n; 1.315 + 1.316 + event_base_start_iocp(data->base, 0); 1.317 + port = event_base_get_iocp(data->base); 1.318 + tt_assert(port); 1.319 + 1.320 + bea1 = bufferevent_async_new(data->base, data->pair[0], 1.321 + BEV_OPT_DEFER_CALLBACKS); 1.322 + bea2 = bufferevent_async_new(data->base, data->pair[1], 1.323 + BEV_OPT_DEFER_CALLBACKS); 1.324 + tt_assert(bea1); 1.325 + tt_assert(bea2); 1.326 + 1.327 + bufferevent_setcb(bea2, async_readcb, NULL, NULL, NULL); 1.328 + bufferevent_enable(bea1, EV_WRITE); 1.329 + bufferevent_enable(bea2, EV_READ); 1.330 + 1.331 + bufferevent_write(bea1, "Hello world", strlen("Hello world")+1); 1.332 + 1.333 + event_base_dispatch(data->base); 1.334 + 1.335 + tt_int_op(got_readcb, ==, 1); 1.336 + n = bufferevent_read(bea2, buf, sizeof(buf)-1); 1.337 + buf[n]='\0'; 1.338 + tt_str_op(buf, ==, "Hello world"); 1.339 + 1.340 +end: 1.341 + bufferevent_free(bea1); 1.342 + bufferevent_free(bea2); 1.343 +} 1.344 + 1.345 + 1.346 +struct testcase_t iocp_testcases[] = { 1.347 + { "port", test_iocp_port, TT_FORK|TT_NEED_THREADS, &basic_setup, NULL }, 1.348 + { "evbuffer", test_iocp_evbuffer, 1.349 + TT_FORK|TT_NEED_SOCKETPAIR|TT_NEED_THREADS, 1.350 + &basic_setup, NULL }, 1.351 + { "bufferevent_async", test_iocp_bufferevent_async, 1.352 + TT_FORK|TT_NEED_SOCKETPAIR|TT_NEED_THREADS|TT_NEED_BASE, 1.353 + &basic_setup, NULL }, 1.354 + END_OF_TESTCASES 1.355 +};