This commit is contained in:
Ryan Williams
2009-12-15 10:36:32 -08:00
22 changed files with 236 additions and 93 deletions

View File

@@ -26,11 +26,11 @@ Thanks To
* Chuck Thier, reporting a bug in processes.py
* Brantley Harris, reporting bug #4
* Taso Du Val, reproing an exception squelching bug, saving children's lives ;-)
* R. Tyler Ballance, bug report on tpool on Windows, help with improving corolocal module
* R. Tyler Ballance, bug report on tpool on Windows, help with improving corolocal module, profile performance report, suggestion use flush that fixed tpool on Windows
* Sergey Shepelev, PEP 8 police :-), reporting bug #5
* Luci Stanescu, for reporting twisted hub bug
* Marcus Cavanaugh, for test case code that has been incredibly useful in tracking down bugs
* Brian Brunswick, for many helpful questions and suggestions on the mailing list
* Cesar Alaniz, for uncovering bugs of great import
* the grugq, for contributing patches, suggestions, and use cases
* Ralf Schmitt, for wsgi/webob incompatibility bug report and suggested fix
* Ralf Schmitt, for wsgi/webob incompatibility bug report and suggested fix

4
NEWS
View File

@@ -13,7 +13,9 @@
* Added support for logging x-forwarded-for header in wsgi.
* api.tcp_server is now deprecated, will be removed in a future release.
* Added instructions on how to generate coverage reports to the documentation.
* Bug fixes in: wsgi.py, twistedr.py, poll.py, greenio.py, util.py, select.py, processes.py
* Renamed GreenFile to Green_fileobject, to better reflect its purpose.
* Deprecated erpc method in tpool.py
* Bug fixes in: wsgi.py, twistedr.py, poll.py, greenio.py, util.py, select.py, processes.py, selects.py
0.9.0
=====

View File

@@ -35,7 +35,7 @@ easy_install eventlet
<p>Alternately, you can download the source tarball:
<ul>
<li><a href="http://pypi.python.org/packages/source/e/eventlet/eventlet-0.9.0.tar.gz#md5=4e14ce5070edd078e3a4e8d6df9a5dc4">eventlet-0.9.0.tar.gz</a></li>
<li><a href="http://pypi.python.org/packages/source/e/eventlet/eventlet-0.9.1.tar.gz">eventlet-0.9.1.tar.gz</a></li>
</ul>
</p>

View File

@@ -1,2 +1,2 @@
version_info = (0, 9, '1pre')
version_info = (0, 9, 1)
__version__ = '%s.%s.%s' % version_info

View File

@@ -11,12 +11,23 @@ from thread import get_ident
from eventlet.greenio import set_nonblocking, GreenSocket, SOCKET_CLOSED, CONNECT_ERR, CONNECT_SUCCESS
orig_socket = __import__('socket')
socket = orig_socket.socket
timeout_exc = orig_socket.timeout
class GreenSSLSocket(__ssl.SSLSocket):
""" This is a green version of the SSLSocket class from the ssl module added
in 2.6. For documentation on it, please see the Python standard
documentation."""
documentation.
Python nonblocking ssl objects don't give errors when the other end
of the socket is closed (they do notice when the other end is shutdown,
though). Any write/read operations will simply hang if the socket is
closed from the other end. There is no obvious fix for this problem;
it appears to be a limitation of Python's ssl object implementation.
A workaround is to set a reasonable timeout on the socket using
settimeout(), and to close/reopen the connection when a timeout
occurs at an unexpected juncture in the code.
"""
# we are inheriting from SSLSocket because its constructor calls
# do_handshake whose behavior we wish to override
def __init__(self, sock, *args, **kw):
@@ -62,12 +73,12 @@ class GreenSSLSocket(__ssl.SSLSocket):
trampoline(self.fileno(),
read=True,
timeout=self.gettimeout(),
timeout_exc=SSLError)
timeout_exc=timeout_exc('timed out'))
elif exc[0] == SSL_ERROR_WANT_WRITE:
trampoline(self.fileno(),
write=True,
timeout=self.gettimeout(),
timeout_exc=SSLError)
timeout_exc=timeout_exc('timed out'))
else:
raise
@@ -121,7 +132,7 @@ class GreenSSLSocket(__ssl.SSLSocket):
raise ValueError("sendto not allowed on instances of %s" %
self.__class__)
else:
trampoline(self.fileno(), write=True, timeout_exc=orig_socket.timeout)
trampoline(self.fileno(), write=True, timeout_exc=timeout_exc('timed out'))
return socket.sendto(self, data, addr, flags)
def sendall (self, data, flags=0):
@@ -146,7 +157,7 @@ class GreenSSLSocket(__ssl.SSLSocket):
raise
if e[0] == errno.EWOULDBLOCK:
trampoline(self.fileno(), write=True,
timeout=self.gettimeout(), timeout_exc=orig_socket.timeout)
timeout=self.gettimeout(), timeout_exc=timeout_exc('timed out'))
if e[0] in SOCKET_CLOSED:
return ''
raise
@@ -169,7 +180,7 @@ class GreenSSLSocket(__ssl.SSLSocket):
raise
if e[0] == errno.EWOULDBLOCK:
trampoline(self.fileno(), read=True,
timeout=self.gettimeout(), timeout_exc=orig_socket.timeout)
timeout=self.gettimeout(), timeout_exc=timeout_exc('timed out'))
if e[0] in SOCKET_CLOSED:
return ''
raise
@@ -177,17 +188,17 @@ class GreenSSLSocket(__ssl.SSLSocket):
def recv_into (self, buffer, nbytes=None, flags=0):
if not self.act_non_blocking:
trampoline(self.fileno(), read=True, timeout=self.gettimeout(), timeout_exc=orig_socket.timeout)
trampoline(self.fileno(), read=True, timeout=self.gettimeout(), timeout_exc=timeout_exc('timed out'))
return super(GreenSSLSocket, self).recv_into(buffer, nbytes, flags)
def recvfrom (self, addr, buflen=1024, flags=0):
if not self.act_non_blocking:
trampoline(self.fileno(), read=True, timeout=self.gettimeout(), timeout_exc=orig_socket.timeout)
trampoline(self.fileno(), read=True, timeout=self.gettimeout(), timeout_exc=timeout_exc('timed out'))
return super(GreenSSLSocket, self).recvfrom(addr, buflen, flags)
def recvfrom_into (self, buffer, nbytes=None, flags=0):
if not self.act_non_blocking:
trampoline(self.fileno(), read=True, timeout=self.gettimeout(), timeout_exc=orig_socket.timeout)
trampoline(self.fileno(), read=True, timeout=self.gettimeout(), timeout_exc=timeout_exc('timed out'))
return super(GreenSSLSocket, self).recvfrom_into(buffer, nbytes, flags)
def unwrap(self):
@@ -224,13 +235,13 @@ class GreenSSLSocket(__ssl.SSLSocket):
except orig_socket.error, exc:
if exc[0] in CONNECT_ERR:
trampoline(self.fileno(), write=True,
timeout=end-time.time(), timeout_exc=orig_socket.timeout)
timeout=end-time.time(), timeout_exc=timeout_exc('timed out'))
elif exc[0] in CONNECT_SUCCESS:
return
else:
raise
if time.time() >= end:
raise orig_socket.timeout
raise timeout_exc('timed out')
def connect(self, addr):
@@ -264,7 +275,7 @@ class GreenSSLSocket(__ssl.SSLSocket):
if e[0] != errno.EWOULDBLOCK:
raise
trampoline(self.fileno(), read=True, timeout=self.gettimeout(),
timeout_exc=orig_socket.timeout)
timeout_exc=timeout_exc('timed out'))
new_ssl = type(self)(newsock,
keyfile=self.keyfile,
@@ -276,7 +287,7 @@ class GreenSSLSocket(__ssl.SSLSocket):
do_handshake_on_connect=self.do_handshake_on_connect,
suppress_ragged_eofs=self.suppress_ragged_eofs)
return (new_ssl, addr)
SSLSocket = GreenSSLSocket

View File

@@ -14,7 +14,7 @@ import warnings
from errno import EWOULDBLOCK, EAGAIN
__all__ = ['GreenSocket', 'GreenFile', 'GreenPipe']
__all__ = ['GreenSocket', 'GreenPipe']
def higher_order_recv(recv_func):
def recv(self, buflen, flags=0):
@@ -167,6 +167,10 @@ class GreenSocket(object):
fd = family_or_realsock
assert not args, args
assert not kwargs, kwargs
try:
orig_timeout = fd.gettimeout()
except AttributeError:
orig_timeout = None
set_nonblocking(fd)
self.fd = fd
@@ -181,6 +185,10 @@ class GreenSocket(object):
# act non-blocking
self.act_non_blocking = False
# import timeout from the other fd if it's distinct
if orig_timeout and orig_timeout is not self.timeout:
self.settimeout(orig_timeout)
@property
def _sock(self):
return self
@@ -294,7 +302,7 @@ class GreenSocket(object):
return socket._fileobject(self.dup(), mode, bufsize)
def makeGreenFile(self, mode='r', bufsize=-1):
return GreenFile(self.dup())
return Green_fileobject(self.dup())
recv = higher_order_recv(socket_recv)
@@ -362,8 +370,9 @@ class GreenSocket(object):
return self.timeout
class GreenFile(object):
class Green_fileobject(object):
"""Green version of socket._fileobject, for use only with regular
sockets."""
newlines = '\r\n'
mode = 'wb+'
@@ -486,7 +495,7 @@ class GreenPipeSocket(GreenSocket):
send = higher_order_send(file_send)
class GreenPipe(GreenFile):
class GreenPipe(Green_fileobject):
def __init__(self, fd):
set_nonblocking(fd)
self.fd = GreenPipeSocket(fd)

View File

@@ -61,6 +61,7 @@ class BaseHub(object):
'exit': [],
}
self.lclass = FdListener
self.silent_timer_exceptions = False
def add(self, evtype, fileno, cb):
""" Signals an intent to or write a particular file descriptor.
@@ -220,8 +221,9 @@ class BaseHub(object):
self.squelch_observer_exception(observer, sys.exc_info())
def squelch_timer_exception(self, timer, exc_info):
traceback.print_exception(*exc_info)
print >>sys.stderr, "Timer raised: %r" % (timer,)
if not self.silent_timer_exceptions:
traceback.print_exception(*exc_info)
print >>sys.stderr, "Timer raised: %r" % (timer,)
def _add_absolute_timer(self, when, info):
# the 0 placeholder makes it easy to bisect_right using (now, 1)

View File

@@ -7,7 +7,7 @@ import time
from eventlet.hubs.hub import BaseHub, READ, WRITE
EXC_MASK = select.POLLERR | select.POLLHUP
READ_MASK = select.POLLIN
READ_MASK = select.POLLIN | select.POLLPRI
WRITE_MASK = select.POLLOUT
class Hub(BaseHub):

View File

@@ -25,9 +25,9 @@ QUIET=False
_rfile = _wfile = None
def _signal_t2e():
from eventlet import util
sent = util.__original_write__(_wfile.fileno(), ' ')
_wfile.write(' ')
_wfile.flush()
_reqq = Queue(maxsize=-1)
_rspq = Queue(maxsize=-1)
@@ -36,9 +36,9 @@ def tpool_trampoline():
while(True):
try:
_c = _rfile.read(1)
assert(_c != "")
except ValueError:
break # will be raised when pipe is closed
assert(_c != "")
while not _rspq.empty():
try:
(e,rv) = _rspq.get(block=False)
@@ -197,10 +197,8 @@ def setup():
sock.listen(50)
csock = util.__original_socket__(socket.AF_INET, socket.SOCK_STREAM)
csock.connect(('localhost', sock.getsockname()[1]))
csock.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1)
nsock, addr = sock.accept()
nsock.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1)
_rfile = greenio.GreenFile(greenio.GreenSocket(csock))
_rfile = greenio.Green_fileobject(greenio.GreenSocket(csock))
_wfile = nsock.makefile()
for i in range(0,_nthreads):
@@ -218,7 +216,8 @@ def killall():
_reqq.put(None)
for thr in _threads.values():
thr.join()
api.kill(_coro)
if _coro:
api.kill(_coro)
_rfile.close()
_wfile.close()
_setup_already = False

View File

@@ -154,7 +154,7 @@ class HttpProtocol(BaseHTTPServer.BaseHTTPRequestHandler):
except greenio.SSL.ZeroReturnError:
self.raw_requestline = ''
except socket.error, e:
if e[0] != errno.EBADF:
if e[0] != errno.EBADF and e[0] != 10053:
raise
self.raw_requestline = ''
@@ -261,11 +261,14 @@ class HttpProtocol(BaseHTTPServer.BaseHTTPRequestHandler):
'Content-Length' not in [h for h, v in headers_set[1]]:
headers_set[1].append(('Content-Length', str(sum(map(len, result)))))
towrite = []
towrite_size = 0
for data in result:
towrite.append(data)
if sum(map(len, towrite)) >= self.minimum_chunk_size:
towrite_size += len(data)
if towrite_size >= self.minimum_chunk_size:
write(''.join(towrite))
towrite = []
towrite_size = 0
if towrite:
write(''.join(towrite))
if not headers_sent or use_chunked[0]:

View File

@@ -4,6 +4,9 @@ import os
import errno
import unittest
# convenience
main = unittest.main
def skipped(func):
""" Decorator that marks a function as skipped. Uses nose's SkipTest exception
if installed. Without nose, this will count skipped tests as passing tests."""
@@ -21,24 +24,39 @@ def skipped(func):
return skipme
def skip_unless(requirement):
""" Decorator that skips a test if the *requirement* does not return True.
*requirement* can be a boolean or a callable that accepts one argument.
The callable will be called with the function to be decorated, and
should return True if the requirement is satisfied.
def skip_if(condition):
""" Decorator that skips a test if the *condition* evaluates True.
*condition* can be a boolean or a callable that accepts one argument.
The callable will be called with the function to be decorated, and
should return True to skip the test.
"""
if isinstance(requirement, bool):
def skipped_wrapper(func):
if not requirement:
return skipped(func)
else:
return func
else:
def skipped_wrapper(func):
if not requirement(func):
return skipped(func)
else:
return func
def skipped_wrapper(func):
if isinstance(condition, bool):
result = condition
else:
result = condition(func)
if result:
return skipped(func)
else:
return func
return skipped_wrapper
def skip_unless(condition):
""" Decorator that skips a test if the *condition* does not return True.
*condition* can be a boolean or a callable that accepts one argument.
The callable will be called with the function to be decorated, and
should return True if the condition is satisfied.
"""
def skipped_wrapper(func):
if isinstance(condition, bool):
result = condition
else:
result = condition(func)
if not result:
return skipped(func)
else:
return func
return skipped_wrapper
@@ -55,10 +73,15 @@ def requires_twisted(func):
def skip_with_libevent(func):
""" Decorator that skips a test if we're using the libevent hub."""
def requirement(_f):
def using_libevent(_f):
from eventlet.api import get_hub
return not('libevent' in type(get_hub()).__module__)
return skip_unless(requirement)(func)
return 'libevent' in type(get_hub()).__module__
return skip_if(using_libevent)(func)
def skip_on_windows(func):
import sys
return skip_if(sys.platform.startswith('win'))(func)
class TestIsTakingTooLong(Exception):
@@ -82,6 +105,20 @@ class LimitedTestCase(unittest.TestCase):
self.timer.cancel()
class SilencedTestCase(LimitedTestCase):
""" Subclass of LimitedTestCase that also silences the printing of timer
exceptions."""
def setUp(self):
from eventlet import api
super(SilencedTestCase, self).setUp()
api.get_hub().silent_timer_exceptions = True
def tearDown(self):
from eventlet import api
super(SilencedTestCase, self).tearDown()
api.get_hub().silent_timer_exceptions = False
def find_command(command):
for dir in os.getenv('PATH', '/usr/bin:/usr/sbin').split(os.pathsep):
p = os.path.join(dir, command)

View File

@@ -1,15 +1,8 @@
from unittest import TestCase, main
from unittest import main, TestCase
from tests import SilencedTestCase
from eventlet import coros, api
class TestEvent(TestCase):
mode = 'static'
def setUp(self):
# raise an exception if we're waiting forever
self._cancel_timeout = api.exc_after(1, RuntimeError('test takes too long'))
def tearDown(self):
self._cancel_timeout.cancel()
class TestEvent(SilencedTestCase):
def test_waiting_for_event(self):
evt = coros.event()
value = 'some stuff'
@@ -81,15 +74,14 @@ class IncrActor(coros.Actor):
if evt: evt.send()
class TestActor(TestCase):
class TestActor(SilencedTestCase):
mode = 'static'
def setUp(self):
# raise an exception if we're waiting forever
self._cancel_timeout = api.exc_after(1, api.TimeoutError())
super(TestActor, self).setUp()
self.actor = IncrActor()
def tearDown(self):
self._cancel_timeout.cancel()
super(TestActor, self).tearDown()
api.kill(self.actor._killer)
def test_cast(self):

View File

@@ -2,6 +2,7 @@ from tests import skipped, LimitedTestCase, skip_with_libevent, TestIsTakingTooL
from unittest import main
from eventlet import api, util, coros, proc, greenio
from eventlet.green.socket import GreenSSLObject
import errno
import os
import socket
import sys
@@ -29,6 +30,17 @@ def min_buf_size():
return test_sock.getsockopt(socket.SOL_SOCKET, socket.SO_SNDBUF)
class TestGreenIo(LimitedTestCase):
def test_connect_timeout(self):
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.settimeout(0.1)
gs = greenio.GreenSocket(s)
try:
self.assertRaises(socket.timeout, gs.connect, ('192.0.2.1', 80))
except socket.error, e:
# unreachable is also a valid outcome
if e[0] != errno.EHOSTUNREACH:
raise
def test_close_with_makefile(self):
def accept_close_early(listener):
# verify that the makefile and the socket are truly independent

View File

@@ -1,12 +1,14 @@
import sys
from unittest import TestCase, main
from tests import LimitedTestCase, main, skip_on_windows
from eventlet import processes, api
class TestEchoPool(TestCase):
class TestEchoPool(LimitedTestCase):
def setUp(self):
super(TestEchoPool, self).setUp()
self.pool = processes.ProcessPool('echo', ["hello"])
@skip_on_windows
def test_echo(self):
result = None
@@ -17,6 +19,7 @@ class TestEchoPool(TestCase):
self.pool.put(proc)
self.assertEquals(result, 'hello\n')
@skip_on_windows
def test_read_eof(self):
proc = self.pool.get()
try:
@@ -24,18 +27,21 @@ class TestEchoPool(TestCase):
self.assertRaises(processes.DeadProcess, proc.read)
finally:
self.pool.put(proc)
@skip_on_windows
def test_empty_echo(self):
p = processes.Process('echo', ['-n'])
self.assertEquals('', p.read())
self.assertRaises(processes.DeadProcess, p.read)
class TestCatPool(TestCase):
class TestCatPool(LimitedTestCase):
def setUp(self):
super(TestCatPool, self).setUp()
api.sleep(0)
self.pool = processes.ProcessPool('cat')
@skip_on_windows
def test_cat(self):
result = None
@@ -49,6 +55,7 @@ class TestCatPool(TestCase):
self.assertEquals(result, 'goodbye')
@skip_on_windows
def test_write_to_dead(self):
result = None
@@ -61,6 +68,7 @@ class TestCatPool(TestCase):
finally:
self.pool.put(proc)
@skip_on_windows
def test_close(self):
result = None
@@ -73,10 +81,12 @@ class TestCatPool(TestCase):
self.pool.put(proc)
class TestDyingProcessesLeavePool(TestCase):
class TestDyingProcessesLeavePool(LimitedTestCase):
def setUp(self):
super(TestDyingProcessesLeavePool, self).setUp()
self.pool = processes.ProcessPool('echo', ['hello'], max_size=1)
@skip_on_windows
def test_dead_process_not_inserted_into_pool(self):
proc = self.pool.get()
try:

View File

@@ -5,7 +5,7 @@ import os
import sys
import tempfile
import time
import unittest
from tests import LimitedTestCase, main, skip_on_windows
import re
import StringIO
@@ -31,12 +31,14 @@ class CoroutineCallingClass(object):
return self._my_dict
class TestSaranwrap(unittest.TestCase):
class TestSaranwrap(LimitedTestCase):
TEST_TIMEOUT=3
def assert_server_exists(self, prox):
self.assert_(saranwrap.status(prox))
prox.foo = 0
self.assertEqual(0, prox.foo)
@skip_on_windows
def test_wrap_tuple(self):
my_tuple = (1, 2)
prox = saranwrap.wrap(my_tuple)
@@ -44,6 +46,7 @@ class TestSaranwrap(unittest.TestCase):
self.assertEqual(prox[1], 2)
self.assertEqual(len(my_tuple), 2)
@skip_on_windows
def test_wrap_string(self):
my_object = "whatever"
prox = saranwrap.wrap(my_object)
@@ -51,6 +54,7 @@ class TestSaranwrap(unittest.TestCase):
self.assertEqual(len(my_object), len(prox))
self.assertEqual(my_object.join(['a', 'b']), prox.join(['a', 'b']))
@skip_on_windows
def test_wrap_uniterable(self):
# here we're treating the exception as just a normal class
prox = saranwrap.wrap(FloatingPointError())
@@ -62,6 +66,7 @@ class TestSaranwrap(unittest.TestCase):
self.assertRaises(IndexError, index)
self.assertRaises(TypeError, key)
@skip_on_windows
def test_wrap_dict(self):
my_object = {'a':1}
prox = saranwrap.wrap(my_object)
@@ -71,6 +76,7 @@ class TestSaranwrap(unittest.TestCase):
self.assertEqual('saran:' + repr(my_object), repr(prox))
self.assertEqual('saran:' + `my_object`, `prox`)
@skip_on_windows
def test_wrap_module_class(self):
prox = saranwrap.wrap(re)
self.assertEqual(saranwrap.Proxy, type(prox))
@@ -78,6 +84,7 @@ class TestSaranwrap(unittest.TestCase):
self.assertEqual(exp.flags, 0)
self.assert_(repr(prox.compile))
@skip_on_windows
def test_wrap_eq(self):
prox = saranwrap.wrap(re)
exp1 = prox.compile('.')
@@ -86,6 +93,7 @@ class TestSaranwrap(unittest.TestCase):
exp3 = prox.compile('/')
self.assert_(exp1 != exp3)
@skip_on_windows
def test_wrap_nonzero(self):
prox = saranwrap.wrap(re)
exp1 = prox.compile('.')
@@ -93,6 +101,7 @@ class TestSaranwrap(unittest.TestCase):
prox2 = saranwrap.Proxy([1, 2, 3])
self.assert_(bool(prox2))
@skip_on_windows
def test_multiple_wraps(self):
prox1 = saranwrap.wrap(re)
prox2 = saranwrap.wrap(re)
@@ -101,6 +110,7 @@ class TestSaranwrap(unittest.TestCase):
del x2
x3 = prox2.compile('.')
@skip_on_windows
def test_dict_passthru(self):
prox = saranwrap.wrap(StringIO)
x = prox.StringIO('a')
@@ -108,25 +118,30 @@ class TestSaranwrap(unittest.TestCase):
# try it all on one line just for the sake of it
self.assertEqual(type(saranwrap.wrap(StringIO).StringIO('a').__dict__), saranwrap.ObjectProxy)
@skip_on_windows
def test_is_value(self):
server = saranwrap.Server(None, None, None)
self.assert_(server.is_value(None))
@skip_on_windows
def test_wrap_getitem(self):
prox = saranwrap.wrap([0,1,2])
self.assertEqual(prox[0], 0)
@skip_on_windows
def test_wrap_setitem(self):
prox = saranwrap.wrap([0,1,2])
prox[1] = 2
self.assertEqual(prox[1], 2)
@skip_on_windows
def test_raising_exceptions(self):
prox = saranwrap.wrap(re)
def nofunc():
prox.never_name_a_function_like_this()
self.assertRaises(AttributeError, nofunc)
@skip_on_windows
def test_unpicklable_server_exception(self):
prox = saranwrap.wrap(saranwrap)
def unpickle():
@@ -137,6 +152,7 @@ class TestSaranwrap(unittest.TestCase):
# It's basically dead
#self.assert_server_exists(prox)
@skip_on_windows
def test_pickleable_server_exception(self):
prox = saranwrap.wrap(saranwrap)
def fperror():
@@ -145,11 +161,13 @@ class TestSaranwrap(unittest.TestCase):
self.assertRaises(FloatingPointError, fperror)
self.assert_server_exists(prox)
@skip_on_windows
def test_print_does_not_break_wrapper(self):
prox = saranwrap.wrap(saranwrap)
prox.print_string('hello')
self.assert_server_exists(prox)
@skip_on_windows
def test_stderr_does_not_break_wrapper(self):
prox = saranwrap.wrap(saranwrap)
prox.err_string('goodbye')
@@ -158,6 +176,7 @@ class TestSaranwrap(unittest.TestCase):
def assertLessThan(self, a, b):
self.assert_(a < b, "%s is not less than %s" % (a, b))
@skip_on_windows
def test_status(self):
prox = saranwrap.wrap(time)
a = prox.gmtime(0)
@@ -176,6 +195,7 @@ class TestSaranwrap(unittest.TestCase):
prox2 = saranwrap.wrap(re)
self.assert_(status['pid'] != saranwrap.status(prox2)['pid'])
@skip_on_windows
def test_del(self):
prox = saranwrap.wrap(time)
delme = prox.gmtime(0)
@@ -189,11 +209,13 @@ class TestSaranwrap(unittest.TestCase):
#print status_after['objects']
self.assertLessThan(status_after['object_count'], status_before['object_count'])
@skip_on_windows
def test_contains(self):
prox = saranwrap.wrap({'a':'b'})
self.assert_('a' in prox)
self.assert_('x' not in prox)
@skip_on_windows
def test_variable_and_keyword_arguments_with_function_calls(self):
import optparse
prox = saranwrap.wrap(optparse)
@@ -202,6 +224,7 @@ class TestSaranwrap(unittest.TestCase):
opts,args = parser.parse_args(["-nfoo"])
self.assertEqual(opts.n, 'foo')
@skip_on_windows
def test_original_proxy_going_out_of_scope(self):
def make_re():
prox = saranwrap.wrap(re)
@@ -224,6 +247,7 @@ class TestSaranwrap(unittest.TestCase):
except AttributeError, e:
pass
@skip_on_windows
def test_not_inheriting_pythonpath(self):
# construct a fake module in the temp directory
temp_dir = tempfile.mkdtemp("saranwrap_test")
@@ -253,6 +277,7 @@ sys_path = sys.path""")
shutil.rmtree(temp_dir)
sys.path.remove(temp_dir)
@skip_on_windows
def test_contention(self):
from tests import saranwrap_test
prox = saranwrap.wrap(saranwrap_test)
@@ -265,6 +290,7 @@ sys_path = sys.path""")
for waiter in waiters:
waiter.wait()
@skip_on_windows
def test_copy(self):
import copy
compound_object = {'a':[1,2,3]}
@@ -278,12 +304,14 @@ sys_path = sys.path""")
make_assertions(copy.copy(prox))
make_assertions(copy.deepcopy(prox))
@skip_on_windows
def test_list_of_functions(self):
return # this test is known to fail, we can implement it sometime in the future if we wish
from tests import saranwrap_test
prox = saranwrap.wrap([saranwrap_test.list_maker])
self.assertEquals(list_maker(), prox[0]())
@skip_on_windows
def test_under_the_hood_coroutines(self):
# so, we want to write a class which uses a coroutine to call
# a function. Then we want to saranwrap that class, have
@@ -302,6 +330,7 @@ sys_path = sys.path""")
'random' in obj_proxy.get_dict(),
'Coroutine in saranwrapped object did not run')
@skip_on_windows
def test_child_process_death(self):
prox = saranwrap.wrap({})
pid = saranwrap.getpid(prox)
@@ -310,17 +339,20 @@ sys_path = sys.path""")
api.sleep(0.1) # need to let the signal handler run
self.assertRaises(OSError, os.kill, pid, 0) # raises OSError if pid doesn't exist
@skip_on_windows
def test_detection_of_server_crash(self):
# make the server crash here
pass
@skip_on_windows
def test_equality_with_local_object(self):
# we'll implement this if there's a use case for it
pass
@skip_on_windows
def test_non_blocking(self):
# here we test whether it's nonblocking
pass
if __name__ == '__main__':
unittest.main()
main()

View File

@@ -40,6 +40,21 @@ class SSLTest(LimitedTestCase):
greenio.shutdown_safe(client)
client.close()
server_coro.wait()
def test_ssl_connect(self):
def serve(listener):
sock, addr = listener.accept()
stuff = sock.read(8192)
sock = api.ssl_listener(('127.0.0.1', 0), certificate_file, private_key_file)
server_coro = coros.execute(serve, sock)
raw_client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
ssl_client = util.wrap_ssl(raw_client)
ssl_client.connect(('127.0.0.1', sock.getsockname()[1]))
ssl_client.write('abc')
greenio.shutdown_safe(ssl_client)
ssl_client.close()
server_coro.wait()
class SocketSSLTest(LimitedTestCase):

View File

@@ -30,9 +30,9 @@ patcher.inject('test.test_ssl',
('threading', threading),
('urllib', urllib))
# these appear to not work due to some wonkiness in the threading
# module... skipping them for now (can't use SkipTest either because
# test_main doesn't understand it)
# these don't pass because nonblocking ssl sockets don't report
# when the socket is closed uncleanly, per the docstring on
# eventlet.green.GreenSSLSocket
# *TODO: fix and restore these tests
ThreadedTests.testProtocolSSL2 = lambda s: None
ThreadedTests.testProtocolSSL3 = lambda s: None

View File

@@ -22,6 +22,7 @@ class TestEvent(LimitedTestCase):
obj = Exception()
e.send(exc=obj)
sleep(0)
sleep(0)
assert log == [('catched', obj)], log
def test_send(self):

View File

@@ -1,4 +1,5 @@
import unittest
from tests import SilencedTestCase
import time
from eventlet import api
from eventlet.green import socket
@@ -29,7 +30,7 @@ class TestDebug(unittest.TestCase):
self.assert_(not api.get_hub().debug)
class TestExceptionInMainloop(unittest.TestCase):
class TestExceptionInMainloop(SilencedTestCase):
def test_sleep(self):
# even if there was an error in the mainloop, the hub should continue to work

View File

@@ -2,14 +2,14 @@ import sys
import unittest
from eventlet.api import sleep, with_timeout
from eventlet import api, proc, coros
from tests import LimitedTestCase, skipped
from tests import SilencedTestCase, skipped
DELAY = 0.01
class ExpectedError(Exception):
pass
class TestLink_Signal(LimitedTestCase):
class TestLink_Signal(SilencedTestCase):
def test_send(self):
s = proc.Source()
@@ -48,7 +48,7 @@ class TestLink_Signal(LimitedTestCase):
self.assertRaises(OSError, s.wait)
class TestProc(LimitedTestCase):
class TestProc(SilencedTestCase):
def test_proc(self):
p = proc.spawn(lambda : 100)
@@ -76,13 +76,13 @@ class TestProc(LimitedTestCase):
self.assertRaises(proc.LinkedCompleted, sleep, 0.1)
class TestCase(LimitedTestCase):
class TestCase(SilencedTestCase):
def link(self, p, listener=None):
getattr(p, self.link_method)(listener)
def tearDown(self):
LimitedTestCase.tearDown(self)
SilencedTestCase.tearDown(self)
self.p.unlink()
def set_links(self, p, first_time, kill_exc_type):
@@ -252,7 +252,7 @@ class TestRaise_link_exception(TestRaise_link):
link_method = 'link_exception'
class TestStuff(unittest.TestCase):
class TestStuff(SilencedTestCase):
def test_wait_noerrors(self):
x = proc.spawn(lambda : 1)
@@ -297,6 +297,7 @@ class TestStuff(unittest.TestCase):
proc.waitall([a, b])
except ExpectedError, ex:
assert 'second' in str(ex), repr(str(ex))
api.sleep(0.2) # sleep to ensure that the other timer is raised
def test_multiple_listeners_error(self):
# if there was an error while calling a callback

View File

@@ -9,12 +9,20 @@ else:
class TestSocketErrors(unittest.TestCase):
def test_connection_refused(self):
# open and close a dummy server to find an unused port
server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server.bind(('127.0.0.1', 0))
server.listen(1)
port = server.getsockname()[1]
server.close()
del server
s = socket.socket()
try:
s.connect(('127.0.0.1', 81))
s.connect(('127.0.0.1', port))
self.fail("Shouldn't have connected")
except socket.error, ex:
code, text = ex.args
assert code in [111, 61], (code, text)
assert code in [111, 61, 10061], (code, text)
assert 'refused' in text.lower(), (code, text)
if __name__=='__main__':

View File

@@ -84,7 +84,12 @@ class ConnectionClosed(Exception):
def read_http(sock):
fd = sock.makeGreenFile()
response_line = fd.readline()
try:
response_line = fd.readline()
except socket.error, exc:
if exc[0] == 10053:
raise ConnectionClosed
raise
if not response_line:
raise ConnectionClosed
raw_headers = fd.readuntil('\r\n\r\n').strip()
@@ -189,8 +194,11 @@ class TestHttpd(LimitedTestCase):
fd = sock.makeGreenFile()
fd.write(request)
result = fd.readline()
status = result.split(' ')[1]
self.assertEqual(status, '414')
if result:
# windows closes the socket before the data is flushed,
# so we never get anything back
status = result.split(' ')[1]
self.assertEqual(status, '414')
fd.close()
def test_007_get_arg(self):