tests: kill all tpool workers in LimitedTestCase

Fixes GH-41 https://github.com/eventlet/eventlet/issues/41
This commit is contained in:
Jakub Stasiak
2013-07-29 23:40:03 +01:00
committed by Sergey Shepelev
parent 5e40ef4bc3
commit dfc08f7947
4 changed files with 74 additions and 69 deletions

View File

@@ -12,7 +12,7 @@ import unittest
import warnings
import eventlet
from eventlet import debug, hubs
from eventlet import debug, hubs, tpool
# convenience for importers
@@ -178,15 +178,8 @@ class LimitedTestCase(unittest.TestCase):
signal.signal(signal.SIGALRM, self.previous_alarm[0])
signal.alarm(self.previous_alarm[1])
try:
hub = hubs.get_hub()
num_readers = len(hub.get_readers())
num_writers = len(hub.get_writers())
assert num_readers == num_writers == 0
except AssertionError:
print "ERROR: Hub not empty"
print debug.format_hub_timers()
print debug.format_hub_listeners()
tpool.killall()
verify_hub_empty()
def assert_less_than(self, a,b,msg=None):
if msg:

View File

@@ -34,6 +34,8 @@ def mysql_requirement(_f):
class MySQLdbTester(LimitedTestCase):
def setUp(self):
super(MySQLdbTester, self).setUp()
self._auth = get_database_auth()['MySQLdb']
self.create_db()
self.connection = None
@@ -51,6 +53,8 @@ class MySQLdbTester(LimitedTestCase):
self.connection.close()
self.drop_db()
super(MySQLdbTester, self).tearDown()
@skip_unless(mysql_requirement)
def create_db(self):
auth = self._auth.copy()

View File

@@ -195,15 +195,10 @@ class _TestBase(LimitedTestCase):
super(_TestBase, self).tearDown()
def spawn_server(self, **kwargs):
"""Spawns a new wsgi server with the given arguments.
Sets self.port to the port of the server, and self.killer is the greenlet
running it.
Kills any previously-running server."""
eventlet.sleep(0) # give previous server a chance to start
if self.killer:
greenthread.kill(self.killer)
"""Spawns a new wsgi server with the given arguments using
:meth:`spawn_thread`.
Sets self.port to the port of the server"""
new_kwargs = dict(max_size=128,
log=self.logfile,
site=self.site)
@@ -213,9 +208,19 @@ class _TestBase(LimitedTestCase):
new_kwargs['sock'] = eventlet.listen(('localhost', 0))
self.port = new_kwargs['sock'].getsockname()[1]
self.killer = eventlet.spawn_n(
wsgi.server,
**new_kwargs)
self.spawn_thread(wsgi.server, **new_kwargs)
def spawn_thread(self, target, **kwargs):
"""Spawns a new greenthread using specified target and arguments.
Kills any previously-running server and sets self.killer to the
greenthread running the target.
"""
eventlet.sleep(0) # give previous server a chance to start
if self.killer:
greenthread.kill(self.killer)
self.killer = eventlet.spawn_n(target, **kwargs)
def set_site(self):
raise NotImplementedError
@@ -1104,12 +1109,15 @@ class TestHttpd(_TestBase):
return
log = StringIO()
# first thing the server does is try to log the IP it's bound to
def run_server():
try:
server = wsgi.server(sock=sock, log=log, site=Site())
wsgi.server(sock=sock, log=log, site=Site())
except ValueError:
log.write('broked')
eventlet.spawn_n(run_server)
self.spawn_thread(run_server)
logval = log.getvalue()
while not logval:
eventlet.sleep(0.0)

View File

@@ -22,20 +22,19 @@ server / client accept() conn - ExplodingConnectionWrap
V V V
connection makefile() file objects - ExplodingSocketFile <-- these raise
"""
# This code relies on a subclass of unittest.TestCase, but is NOT a test.
# Should NOT be run by nose to avoid potential monkeypatch contamination.
# - Not just @skipped; nose must not consider this a test at all:
__test__ = False
import eventlet
import socket
import sys
from cStringIO import StringIO
import tests.wsgi_test
# no standard tests in this file, ignore
__test__ = False
# This test might make you wince
class NaughtySocketAcceptWrap(object):
# server's socket.accept(); patches resulting connection sockets
@@ -114,50 +113,51 @@ class ExplodingSocketFile(socket._fileobject):
return super(self.__class__, self).readline(*args, **kwargs)
for debug in (False, True):
print "SEPERATOR_SENTINEL"
print "debug set to: %s" % debug
if __name__ == '__main__':
for debug in (False, True):
print "SEPERATOR_SENTINEL"
print "debug set to: %s" % debug
server_sock = eventlet.listen(('localhost', 0))
server_addr = server_sock.getsockname()
sock_wrap = NaughtySocketAcceptWrap(server_sock)
server_sock = eventlet.listen(('localhost', 0))
server_addr = server_sock.getsockname()
sock_wrap = NaughtySocketAcceptWrap(server_sock)
eventlet.spawn_n(
eventlet.wsgi.server,
debug=debug,
log=sys.stdout,
max_size=128,
site=tests.wsgi_test.Site(),
sock=server_sock,
)
eventlet.spawn_n(
eventlet.wsgi.server,
debug=debug,
log=sys.stdout,
max_size=128,
site=tests.wsgi_test.Site(),
sock=server_sock,
)
try:
# req #1 - normal
sock1 = eventlet.connect(server_addr)
sock1.settimeout(0.1)
fd1 = sock1.makefile('rw')
fd1.write('GET / HTTP/1.1\r\nHost: localhost\r\n\r\n')
fd1.flush()
tests.wsgi_test.read_http(sock1)
# let the server socket ops catch up, set bomb
eventlet.sleep(0)
print "arming..."
sock_wrap.arm()
# req #2 - old conn, post-arm - timeout
fd1.write('GET / HTTP/1.1\r\nHost: localhost\r\n\r\n')
fd1.flush()
try:
# req #1 - normal
sock1 = eventlet.connect(server_addr)
sock1.settimeout(0.1)
fd1 = sock1.makefile('rw')
fd1.write('GET / HTTP/1.1\r\nHost: localhost\r\n\r\n')
fd1.flush()
tests.wsgi_test.read_http(sock1)
assert False, 'Expected ConnectionClosed exception'
except tests.wsgi_test.ConnectionClosed:
pass
fd1.close()
sock1.close()
finally:
# reset streams, then output trapped tracebacks
sock_wrap.unwrap()
# check output asserts in tests.wsgi_test.TestHttpd
# test_143_server_connection_timeout_exception
# let the server socket ops catch up, set bomb
eventlet.sleep(0)
print "arming..."
sock_wrap.arm()
# req #2 - old conn, post-arm - timeout
fd1.write('GET / HTTP/1.1\r\nHost: localhost\r\n\r\n')
fd1.flush()
try:
tests.wsgi_test.read_http(sock1)
assert False, 'Expected ConnectionClosed exception'
except tests.wsgi_test.ConnectionClosed:
pass
fd1.close()
sock1.close()
finally:
# reset streams, then output trapped tracebacks
sock_wrap.unwrap()
# check output asserts in tests.wsgi_test.TestHttpd
# test_143_server_connection_timeout_exception