1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/ipc/chromium/src/third_party/libevent/test/regress_et.c Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,207 @@ 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 +#include "../util-internal.h" 1.30 +#include "event2/event-config.h" 1.31 + 1.32 +#ifdef WIN32 1.33 +#include <winsock2.h> 1.34 +#endif 1.35 +#include <sys/types.h> 1.36 +#include <sys/stat.h> 1.37 +#ifdef _EVENT_HAVE_SYS_SOCKET_H 1.38 +#include <sys/socket.h> 1.39 +#endif 1.40 +#include <fcntl.h> 1.41 +#include <stdlib.h> 1.42 +#include <stdio.h> 1.43 +#include <string.h> 1.44 +#ifndef WIN32 1.45 +#include <sys/time.h> 1.46 +#include <unistd.h> 1.47 +#endif 1.48 +#include <errno.h> 1.49 + 1.50 +#include "event2/event.h" 1.51 +#include "event2/util.h" 1.52 + 1.53 +#include "regress.h" 1.54 + 1.55 +static int was_et = 0; 1.56 + 1.57 +static void 1.58 +read_cb(evutil_socket_t fd, short event, void *arg) 1.59 +{ 1.60 + char buf; 1.61 + int len; 1.62 + 1.63 + len = recv(fd, &buf, sizeof(buf), 0); 1.64 + 1.65 + called++; 1.66 + if (event & EV_ET) 1.67 + was_et = 1; 1.68 + 1.69 + if (!len) 1.70 + event_del(arg); 1.71 +} 1.72 + 1.73 +#ifndef SHUT_WR 1.74 +#define SHUT_WR 1 1.75 +#endif 1.76 + 1.77 +#ifdef WIN32 1.78 +#define LOCAL_SOCKETPAIR_AF AF_INET 1.79 +#else 1.80 +#define LOCAL_SOCKETPAIR_AF AF_UNIX 1.81 +#endif 1.82 + 1.83 +static void 1.84 +test_edgetriggered(void *et) 1.85 +{ 1.86 + struct event *ev = NULL; 1.87 + struct event_base *base = NULL; 1.88 + const char *test = "test string"; 1.89 + evutil_socket_t pair[2] = {-1,-1}; 1.90 + int supports_et; 1.91 + 1.92 + /* On Linux 3.2.1 (at least, as patched by Fedora and tested by Nick), 1.93 + * doing a "recv" on an AF_UNIX socket resets the readability of the 1.94 + * socket, even though there is no state change, so we don't actually 1.95 + * get edge-triggered behavior. Yuck! Linux 3.1.9 didn't have this 1.96 + * problem. 1.97 + */ 1.98 +#ifdef __linux__ 1.99 + if (evutil_ersatz_socketpair(AF_INET, SOCK_STREAM, 0, pair) == -1) { 1.100 + tt_abort_perror("socketpair"); 1.101 + } 1.102 +#else 1.103 + if (evutil_socketpair(LOCAL_SOCKETPAIR_AF, SOCK_STREAM, 0, pair) == -1) { 1.104 + tt_abort_perror("socketpair"); 1.105 + } 1.106 +#endif 1.107 + 1.108 + called = was_et = 0; 1.109 + 1.110 + tt_int_op(send(pair[0], test, (int)strlen(test)+1, 0), >, 0); 1.111 + shutdown(pair[0], SHUT_WR); 1.112 + 1.113 + /* Initalize the event library */ 1.114 + base = event_base_new(); 1.115 + 1.116 + if (!strcmp(event_base_get_method(base), "epoll") || 1.117 + !strcmp(event_base_get_method(base), "epoll (with changelist)") || 1.118 + !strcmp(event_base_get_method(base), "kqueue")) 1.119 + supports_et = 1; 1.120 + else 1.121 + supports_et = 0; 1.122 + 1.123 + TT_BLATHER(("Checking for edge-triggered events with %s, which should %s" 1.124 + "support edge-triggering", event_base_get_method(base), 1.125 + supports_et?"":"not ")); 1.126 + 1.127 + /* Initalize one event */ 1.128 + ev = event_new(base, pair[1], EV_READ|EV_ET|EV_PERSIST, read_cb, &ev); 1.129 + 1.130 + event_add(ev, NULL); 1.131 + 1.132 + /* We're going to call the dispatch function twice. The first invocation 1.133 + * will read a single byte from pair[1] in either case. If we're edge 1.134 + * triggered, we'll only see the event once (since we only see transitions 1.135 + * from no data to data), so the second invocation of event_base_loop will 1.136 + * do nothing. If we're level triggered, the second invocation of 1.137 + * event_base_loop will also activate the event (because there's still 1.138 + * data to read). */ 1.139 + event_base_loop(base,EVLOOP_NONBLOCK|EVLOOP_ONCE); 1.140 + event_base_loop(base,EVLOOP_NONBLOCK|EVLOOP_ONCE); 1.141 + 1.142 + if (supports_et) { 1.143 + tt_int_op(called, ==, 1); 1.144 + tt_assert(was_et); 1.145 + } else { 1.146 + tt_int_op(called, ==, 2); 1.147 + tt_assert(!was_et); 1.148 + } 1.149 + 1.150 + end: 1.151 + if (ev) { 1.152 + event_del(ev); 1.153 + event_free(ev); 1.154 + } 1.155 + if (base) 1.156 + event_base_free(base); 1.157 + evutil_closesocket(pair[0]); 1.158 + evutil_closesocket(pair[1]); 1.159 +} 1.160 + 1.161 +static void 1.162 +test_edgetriggered_mix_error(void *data_) 1.163 +{ 1.164 + struct basic_test_data *data = data_; 1.165 + struct event_base *base = NULL; 1.166 + struct event *ev_et=NULL, *ev_lt=NULL; 1.167 + 1.168 +#ifdef _EVENT_DISABLE_DEBUG_MODE 1.169 + if (1) 1.170 + tt_skip(); 1.171 +#endif 1.172 + 1.173 + event_enable_debug_mode(); 1.174 + 1.175 + base = event_base_new(); 1.176 + 1.177 + /* try mixing edge-triggered and level-triggered to make sure it fails*/ 1.178 + ev_et = event_new(base, data->pair[0], EV_READ|EV_ET, read_cb, ev_et); 1.179 + tt_assert(ev_et); 1.180 + ev_lt = event_new(base, data->pair[0], EV_READ, read_cb, ev_lt); 1.181 + tt_assert(ev_lt); 1.182 + 1.183 + /* Add edge-triggered, then level-triggered. Get an error. */ 1.184 + tt_int_op(0, ==, event_add(ev_et, NULL)); 1.185 + tt_int_op(-1, ==, event_add(ev_lt, NULL)); 1.186 + tt_int_op(EV_READ, ==, event_pending(ev_et, EV_READ, NULL)); 1.187 + tt_int_op(0, ==, event_pending(ev_lt, EV_READ, NULL)); 1.188 + 1.189 + tt_int_op(0, ==, event_del(ev_et)); 1.190 + /* Add level-triggered, then edge-triggered. Get an error. */ 1.191 + tt_int_op(0, ==, event_add(ev_lt, NULL)); 1.192 + tt_int_op(-1, ==, event_add(ev_et, NULL)); 1.193 + tt_int_op(EV_READ, ==, event_pending(ev_lt, EV_READ, NULL)); 1.194 + tt_int_op(0, ==, event_pending(ev_et, EV_READ, NULL)); 1.195 + 1.196 +end: 1.197 + if (ev_et) 1.198 + event_free(ev_et); 1.199 + if (ev_lt) 1.200 + event_free(ev_lt); 1.201 + if (base) 1.202 + event_base_free(base); 1.203 +} 1.204 + 1.205 +struct testcase_t edgetriggered_testcases[] = { 1.206 + { "et", test_edgetriggered, TT_FORK, NULL, NULL }, 1.207 + { "et_mix_error", test_edgetriggered_mix_error, 1.208 + TT_FORK|TT_NEED_SOCKETPAIR|TT_NO_LOGS, &basic_setup, NULL }, 1.209 + END_OF_TESTCASES 1.210 +};