tests: kill all tpool workers in LimitedTestCase
Fixes GH-41 https://github.com/eventlet/eventlet/issues/41
This commit is contained in:

committed by
Sergey Shepelev

parent
5e40ef4bc3
commit
dfc08f7947
@@ -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:
|
||||
|
@@ -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()
|
||||
|
@@ -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)
|
||||
|
@@ -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
|
||||
|
Reference in New Issue
Block a user