diff options
Diffstat (limited to 'Lib/test/test_socketserver.py')
| -rw-r--r-- | Lib/test/test_socketserver.py | 58 |
1 files changed, 49 insertions, 9 deletions
diff --git a/Lib/test/test_socketserver.py b/Lib/test/test_socketserver.py index a098edd..160f5b8 100644 --- a/Lib/test/test_socketserver.py +++ b/Lib/test/test_socketserver.py @@ -3,21 +3,23 @@ Test suite for socketserver. """ import contextlib -import errno import imp import os import select import signal import socket +import select +import errno import tempfile -import threading -import time import unittest import socketserver import test.support -from test.support import reap_children, verbose -from test.support import TESTFN as TEST_FILE +from test.support import reap_children, reap_threads, verbose +try: + import threading +except ImportError: + threading = None test.support.requires("network") @@ -32,8 +34,11 @@ def signal_alarm(n): if hasattr(signal, 'alarm'): signal.alarm(n) +# Remember real select() to avoid interferences with mocking +_real_select = select.select + def receive(sock, n, timeout=20): - r, w, x = select.select([sock], [], [], timeout) + r, w, x = _real_select([sock], [], [], timeout) if sock in r: return sock.recv(n) else: @@ -53,7 +58,7 @@ if HAVE_UNIX_SOCKETS: def simple_subprocess(testcase): pid = os.fork() if pid == 0: - # Don't throw an exception; it would be caught by the test harness. + # Don't raise an exception; it would be caught by the test harness. os._exit(72) yield None pid2, status = os.waitpid(pid, 0) @@ -66,7 +71,7 @@ class SocketServerTest(unittest.TestCase): """Test all socket servers.""" def setUp(self): - signal_alarm(20) # Kill deadlocks after 20 seconds. + signal_alarm(60) # Kill deadlocks after 60 seconds. self.port_seed = 0 self.test_files = [] @@ -123,6 +128,7 @@ class SocketServerTest(unittest.TestCase): self.assertEqual(server.server_address, server.socket.getsockname()) return server + @reap_threads def run_server(self, svrcls, hdlrbase, testfunc): server = self.make_server(self.pickaddr(svrcls.address_family), svrcls, hdlrbase) @@ -149,6 +155,7 @@ class SocketServerTest(unittest.TestCase): if verbose: print("waiting for server") server.shutdown() t.join() + server.server_close() if verbose: print("done") def stream_examine(self, proto, addr): @@ -224,6 +231,38 @@ class SocketServerTest(unittest.TestCase): socketserver.DatagramRequestHandler, self.dgram_examine) + @contextlib.contextmanager + def mocked_select_module(self): + """Mocks the select.select() call to raise EINTR for first call""" + old_select = select.select + + class MockSelect: + def __init__(self): + self.called = 0 + + def __call__(self, *args): + self.called += 1 + if self.called == 1: + # raise the exception on first call + raise select.error(errno.EINTR, os.strerror(errno.EINTR)) + else: + # Return real select value for consecutive calls + return old_select(*args) + + select.select = MockSelect() + try: + yield select.select + finally: + select.select = old_select + + def test_InterruptServerSelectCall(self): + with self.mocked_select_module() as mock_select: + pid = self.run_server(socketserver.TCPServer, + socketserver.StreamRequestHandler, + self.stream_examine) + # Make sure select was called again: + self.assertGreater(mock_select.called, 1) + # Alas, on Linux (at least) recvfrom() doesn't return a meaningful # client address so this cannot work: @@ -244,6 +283,7 @@ class SocketServerTest(unittest.TestCase): # socketserver.DatagramRequestHandler, # self.dgram_examine) + @reap_threads def test_shutdown(self): # Issue #2302: shutdown() should always succeed in making an # other thread leave serve_forever(). @@ -267,6 +307,7 @@ class SocketServerTest(unittest.TestCase): s.shutdown() for t, s in threads: t.join() + s.server_close() def test_main(): @@ -278,4 +319,3 @@ def test_main(): if __name__ == "__main__": test_main() - signal_alarm(3) # Shutdown shouldn't take more than 3 seconds. |
