未验证 提交 5ae7327e 编写于 作者: B Ben Darnell 提交者: GitHub

Merge pull request #2327 from bdarnell/test-dont-close

testing: Don't close the event loop if we didn't create it
...@@ -11,6 +11,11 @@ import platform ...@@ -11,6 +11,11 @@ import platform
import traceback import traceback
import warnings import warnings
try:
import asyncio
except ImportError:
asyncio = None
@contextlib.contextmanager @contextlib.contextmanager
def set_environ(name, value): def set_environ(name, value):
...@@ -307,5 +312,30 @@ class GenTest(AsyncTestCase): ...@@ -307,5 +312,30 @@ class GenTest(AsyncTestCase):
self.finished = True self.finished = True
@unittest.skipIf(asyncio is None, "asyncio module not present")
class GetNewIOLoopTest(AsyncTestCase):
def get_new_ioloop(self):
# Use the current loop instead of creating a new one here.
return ioloop.IOLoop.current()
def setUp(self):
# This simulates the effect of an asyncio test harness like
# pytest-asyncio.
self.orig_loop = asyncio.get_event_loop()
self.new_loop = asyncio.new_event_loop()
asyncio.set_event_loop(self.new_loop)
super(GetNewIOLoopTest, self).setUp()
def tearDown(self):
super(GetNewIOLoopTest, self).tearDown()
# AsyncTestCase must not affect the existing asyncio loop.
self.assertFalse(asyncio.get_event_loop().is_closed())
asyncio.set_event_loop(self.orig_loop)
self.new_loop.close()
def test_loop(self):
self.assertIs(self.io_loop.asyncio_loop, self.new_loop)
if __name__ == '__main__': if __name__ == '__main__':
unittest.main() unittest.main()
...@@ -74,6 +74,12 @@ else: ...@@ -74,6 +74,12 @@ else:
import unittest # type: ignore import unittest # type: ignore
if asyncio is None:
_NON_OWNED_IOLOOPS = ()
else:
import tornado.platform.asyncio
_NON_OWNED_IOLOOPS = tornado.platform.asyncio.AsyncIOMainLoop
def bind_unused_port(reuse_port=False): def bind_unused_port(reuse_port=False):
"""Binds a server socket to an available port on localhost. """Binds a server socket to an available port on localhost.
...@@ -216,6 +222,7 @@ class AsyncTestCase(unittest.TestCase): ...@@ -216,6 +222,7 @@ class AsyncTestCase(unittest.TestCase):
# Clean up Subprocess, so it can be used again with a new ioloop. # Clean up Subprocess, so it can be used again with a new ioloop.
Subprocess.uninitialize() Subprocess.uninitialize()
self.io_loop.clear_current() self.io_loop.clear_current()
if not isinstance(self.io_loop, _NON_OWNED_IOLOOPS):
# Try to clean up any file descriptors left open in the ioloop. # Try to clean up any file descriptors left open in the ioloop.
# This avoids leaks, especially when tests are run repeatedly # This avoids leaks, especially when tests are run repeatedly
# in the same process with autoreload (because curl does not # in the same process with autoreload (because curl does not
...@@ -229,9 +236,15 @@ class AsyncTestCase(unittest.TestCase): ...@@ -229,9 +236,15 @@ class AsyncTestCase(unittest.TestCase):
self.__rethrow() self.__rethrow()
def get_new_ioloop(self): def get_new_ioloop(self):
"""Creates a new `.IOLoop` for this test. May be overridden in """Returns the `.IOLoop` to use for this test.
subclasses for tests that require a specific `.IOLoop` (usually
the singleton `.IOLoop.instance()`). By default, a new `.IOLoop` is created for each test.
Subclasses may override this method to return
`.IOLoop.current()` if it is not appropriate to use a new
`.IOLoop` in each tests (for example, if there are global
singletons using the default `.IOLoop`) or if a per-test event
loop is being provided by another system (such as
``pytest-asyncio``).
""" """
return IOLoop() return IOLoop()
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册