2
Test suite for socketserver.
19
from test.support import reap_children, verbose, TestSkipped
20
from test.support import TESTFN as TEST_FILE
22
test.support.requires("network")
24
TEST_STR = b"hello world\n"
25
HOST = test.support.HOST
27
HAVE_UNIX_SOCKETS = hasattr(socket, "AF_UNIX")
28
HAVE_FORKING = hasattr(os, "fork") and os.name != "os2"
31
"""Call signal.alarm when it exists (i.e. not on Windows)."""
32
if hasattr(signal, 'alarm'):
35
def receive(sock, n, timeout=20):
36
r, w, x = select.select([sock], [], [], timeout)
40
raise RuntimeError("timed out on %r" % (sock,))
43
class ForkingUnixStreamServer(socketserver.ForkingMixIn,
44
socketserver.UnixStreamServer):
47
class ForkingUnixDatagramServer(socketserver.ForkingMixIn,
48
socketserver.UnixDatagramServer):
52
@contextlib.contextmanager
53
def simple_subprocess(testcase):
56
# Don't throw an exception; it would be caught by the test harness.
59
pid2, status = os.waitpid(pid, 0)
60
testcase.assertEquals(pid2, pid)
61
testcase.assertEquals(72 << 8, status)
64
class SocketServerTest(unittest.TestCase):
65
"""Test all socket servers."""
68
signal_alarm(20) # Kill deadlocks after 20 seconds.
73
signal_alarm(0) # Didn't deadlock.
76
for fn in self.test_files:
81
self.test_files[:] = []
83
def pickaddr(self, proto):
84
if proto == socket.AF_INET:
87
# XXX: We need a way to tell AF_UNIX to pick its own name
88
# like AF_INET provides port==0.
92
fn = tempfile.mktemp(prefix='unix_socket.', dir=dir)
94
# AF_UNIX socket names on OS/2 require a specific prefix
95
# which can't include a drive letter and must also use
96
# backslashes as directory separators
99
if fn[0] in (os.sep, os.altsep):
102
fn = fn.replace(os.sep, os.altsep)
104
fn = fn.replace(os.altsep, os.sep)
105
self.test_files.append(fn)
108
def make_server(self, addr, svrcls, hdlrbase):
109
class MyServer(svrcls):
110
def handle_error(self, request, client_address):
111
self.close_request(request)
115
class MyHandler(hdlrbase):
117
line = self.rfile.readline()
118
self.wfile.write(line)
120
if verbose: print("creating server")
121
server = MyServer(addr, MyHandler)
122
self.assertEquals(server.server_address, server.socket.getsockname())
125
def run_server(self, svrcls, hdlrbase, testfunc):
126
server = self.make_server(self.pickaddr(svrcls.address_family),
128
# We had the OS pick a port, so pull the real address out of
130
addr = server.server_address
132
print("ADDR =", addr)
133
print("CLASS =", svrcls)
135
t = threading.Thread(
136
name='%s serving' % svrcls,
137
target=server.serve_forever,
138
# Short poll interval to make the test finish quickly.
139
# Time between requests is short enough that we won't wake
140
# up spuriously too many times.
141
kwargs={'poll_interval':0.01})
142
t.daemon = True # In case this function raises.
144
if verbose: print("server running")
146
if verbose: print("test client", i)
147
testfunc(svrcls.address_family, addr)
148
if verbose: print("waiting for server")
151
if verbose: print("done")
153
def stream_examine(self, proto, addr):
154
s = socket.socket(proto, socket.SOCK_STREAM)
157
buf = data = receive(s, 100)
158
while data and b'\n' not in buf:
159
data = receive(s, 100)
161
self.assertEquals(buf, TEST_STR)
164
def dgram_examine(self, proto, addr):
165
s = socket.socket(proto, socket.SOCK_DGRAM)
166
s.sendto(TEST_STR, addr)
167
buf = data = receive(s, 100)
168
while data and b'\n' not in buf:
169
data = receive(s, 100)
171
self.assertEquals(buf, TEST_STR)
174
def test_TCPServer(self):
175
self.run_server(socketserver.TCPServer,
176
socketserver.StreamRequestHandler,
179
def test_ThreadingTCPServer(self):
180
self.run_server(socketserver.ThreadingTCPServer,
181
socketserver.StreamRequestHandler,
185
def test_ForkingTCPServer(self):
186
with simple_subprocess(self):
187
self.run_server(socketserver.ForkingTCPServer,
188
socketserver.StreamRequestHandler,
191
if HAVE_UNIX_SOCKETS:
192
def test_UnixStreamServer(self):
193
self.run_server(socketserver.UnixStreamServer,
194
socketserver.StreamRequestHandler,
197
def test_ThreadingUnixStreamServer(self):
198
self.run_server(socketserver.ThreadingUnixStreamServer,
199
socketserver.StreamRequestHandler,
203
def test_ForkingUnixStreamServer(self):
204
with simple_subprocess(self):
205
self.run_server(ForkingUnixStreamServer,
206
socketserver.StreamRequestHandler,
209
def test_UDPServer(self):
210
self.run_server(socketserver.UDPServer,
211
socketserver.DatagramRequestHandler,
214
def test_ThreadingUDPServer(self):
215
self.run_server(socketserver.ThreadingUDPServer,
216
socketserver.DatagramRequestHandler,
220
def test_ForkingUDPServer(self):
221
with simple_subprocess(self):
222
self.run_server(socketserver.ForkingUDPServer,
223
socketserver.DatagramRequestHandler,
226
# Alas, on Linux (at least) recvfrom() doesn't return a meaningful
227
# client address so this cannot work:
229
# if HAVE_UNIX_SOCKETS:
230
# def test_UnixDatagramServer(self):
231
# self.run_server(socketserver.UnixDatagramServer,
232
# socketserver.DatagramRequestHandler,
233
# self.dgram_examine)
235
# def test_ThreadingUnixDatagramServer(self):
236
# self.run_server(socketserver.ThreadingUnixDatagramServer,
237
# socketserver.DatagramRequestHandler,
238
# self.dgram_examine)
241
# def test_ForkingUnixDatagramServer(self):
242
# self.run_server(socketserver.ForkingUnixDatagramServer,
243
# socketserver.DatagramRequestHandler,
244
# self.dgram_examine)
249
# If the import lock is held, the threads will hang
250
raise TestSkipped("can't run when import lock is held")
252
test.support.run_unittest(SocketServerTest)
254
if __name__ == "__main__":
256
signal_alarm(3) # Shutdown shouldn't take more than 3 seconds.