summaryrefslogtreecommitdiffstats
path: root/Lib/test/test_socketserver.py
diff options
context:
space:
mode:
Diffstat (limited to 'Lib/test/test_socketserver.py')
-rw-r--r--Lib/test/test_socketserver.py58
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.