Skip to content

Commit c443e33

Browse files
gh-155027: Make test_asyncio's socket harness able to fail a test
_abort_socket_test() called self.fail() from the client/server thread. The resulting AssertionError escapes Thread.run() without ever reaching TestCase.run(), so an error in the server half of a socket test did not fail it. Record the exception instead and re-raise it from tearDown(). Also stop the event loop with call_soon_threadsafe() rather than calling loop.stop() directly from a non-main thread.
1 parent a646c99 commit c443e33

2 files changed

Lines changed: 22 additions & 2 deletions

File tree

Lib/test/test_asyncio/functional.py

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ def setUp(self):
2828

2929
self.loop.set_exception_handler(self.loop_exception_handler)
3030
self.__unhandled_exceptions = []
31+
self.__abort_exception = None
3132

3233
def tearDown(self):
3334
try:
@@ -38,9 +39,13 @@ def tearDown(self):
3839
pprint.pprint(self.__unhandled_exceptions)
3940
self.fail('unexpected calls to loop.call_exception_handler()')
4041

42+
if self.__abort_exception is not None:
43+
raise self.__abort_exception
44+
4145
finally:
4246
asyncio.set_event_loop(None)
4347
self.loop = None
48+
self.__abort_exception = None
4449

4550
def tcp_server(self, server_prog, *,
4651
family=socket.AF_INET,
@@ -104,10 +109,18 @@ def unix_sock_name(self):
104109
pass
105110

106111
def _abort_socket_test(self, ex):
112+
# This runs in the client/server thread, not the main thread, so
113+
# it must not call self.fail(): the AssertionError would escape
114+
# Thread.run() without failing the test. Stash the exception and
115+
# let tearDown() re-raise it on the main thread.
107116
try:
108-
self.loop.stop()
117+
self.loop.call_soon_threadsafe(self.loop.stop)
118+
except RuntimeError:
119+
# The loop is already closed; nothing left to stop.
120+
pass
109121
finally:
110-
self.fail(ex)
122+
if self.__abort_exception is None:
123+
self.__abort_exception = ex
111124

112125

113126
##############################################################################
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
Fix ``test_asyncio``'s socket test harness so that a failure in the client
2+
or server thread actually fails the test. ``_abort_socket_test()`` called
3+
``self.fail()`` from a worker thread, where the resulting
4+
:exc:`AssertionError` cannot fail the test; it now records the exception and
5+
re-raises it on the main thread. It also stops the event loop with
6+
:meth:`~asyncio.loop.call_soon_threadsafe` rather than calling
7+
:meth:`~asyncio.loop.stop` directly from a non-main thread.

0 commit comments

Comments
 (0)