gh-94609: Make test_ssl.ThreadedEchoServer exceptions appear in a main thread#92475
gh-94609: Make test_ssl.ThreadedEchoServer exceptions appear in a main thread#92475arhadthedev wants to merge 92 commits intopython:mainfrom
Conversation
Instead of threads and flags, employ high-level concurrency primitives like tasks and futures. A thread pool allows to run tests in parallel so it is future-proof.
Start delegating all exceptions to a main, tester thread.
- thread creation for each new client has no use in single-shot
disposable servers that need to be created fresh for every test case
anyway
- stop-flag has no use either; there is no interactive session as well
as waiting for other users. To test server-side connection abruption,
instruct a server instance in advance
- wrap_conn either modified self.sslconn and returned True, or swallowed
exceptions and returned False. Now it either return sslconn directly
or lets an exception to bubble up through a future into a main thread.
The main thread, in its turn, either expects it with assertRaises() or
lets it bubble further so the test case is reported as failed
- transparent bubbling up means no explicit collection of error
messages in conn_errors. Let unittest package do this job for us
- universal read-write-close operations are changed from inner ifs to
assignment of specific lambda functions
- constant repetition of `if support.verbose and chatty:` //
`sys.stdout.write(' server: ...\n')` is moved into log()
- chatty and connectionchatty flags are merged to form a single story of
communication between a client and a server
- the first usage of ThreadedEchoServer is on line 1286 while the server
itself was declared starting with line 2557; the new implementation
is put before the first usage for sequential narration
In ThreadedEchoServer chatty=True by default so omit it.
1ef0c2c to
610e8e1
Compare
Force clients to wait on a server socket while the server worker thread starts up, instead of erroring on unavailable host. For this, open the socket in a main thread. Server socket timeout has no use because the only operation it limits is listen(). To have it permawaiting we need a main thread interrupted without terminating the whole program; that's possible under a debugger only.
610e8e1 to
d5c4762
Compare
…t breaks it with a long-live thread pool
|
A thread pool triggers |
Not relevant anymore. The creationa and destruction happens for some modules only. Whatever, it's ready for a review. |
This reverts commit b410384.
|
Everything is green and ready for a review (after the release blocker crunch is over, of course). |
|
@tiran Would you mind to look at this PR? It adds a unified separate-threaded |
| def _release(): | ||
| global _thread_pool | ||
| _thread_pool = None | ||
|
|
||
|
|
||
| def init(): | ||
| global _thread_pool | ||
| _thread_pool = ThreadPoolExecutor() | ||
| unittest.addModuleCleanup(_release) |
There was a problem hiding this comment.
I've added init() to avoid a modified environment test failure due to a leaked object. If there's a better solution, I'll use that instead.
Feature or enhancement
This PR:
test.test_ssl.Serverthat is liketest.test_ssl.ThreadedEchoServerbut (1) implemented as a context manager and (2) replaces plain printing of server-side tracebacks with bubbling the exception up between threads through a future. The (2) is implemented as follows:ConnectionAbortedError/ConnectionResetErrorhence knowing that the future is going to have a server exception insidesetUp/tearDownPitch
*_failtest cases) do not flood a console with unnecessary stack traces (and a heart of a watcher with fear)assertRaisesin a main thread; unexpected exceptions will migrate into a Tests Result report footnote failing the run so no need to scroll the log hundreds lines upTODO
Plans for future PRs:
ThreadedEchoServerasyncoreliketest_ftpandtest_logging)test_sslis too verbose #94609