blob: 847859d06bd9c3cb1a236f1b0aa425df475dfa81 [file] [log] [blame]
Georg Brandl61fdd712008-02-02 11:05:00 +00001"""
Georg Brandle152a772008-05-24 18:31:28 +00002Test suite for SocketServer.py.
Georg Brandl61fdd712008-02-02 11:05:00 +00003"""
Guido van Rossum39f1b362001-07-10 11:52:38 +00004
Jeffrey Yasskin392c1592008-02-28 18:03:15 +00005import contextlib
Georg Brandl61fdd712008-02-02 11:05:00 +00006import imp
Jeffrey Yasskin180997b2008-02-28 05:53:18 +00007import os
Guido van Rossum39f1b362001-07-10 11:52:38 +00008import select
Jeffrey Yasskin180997b2008-02-28 05:53:18 +00009import signal
10import socket
Antoine Pitroufa1d8412012-04-09 00:47:24 +020011import select
12import errno
Jeffrey Yasskin180997b2008-02-28 05:53:18 +000013import tempfile
Georg Brandl61fdd712008-02-02 11:05:00 +000014import unittest
Georg Brandle152a772008-05-24 18:31:28 +000015import SocketServer
Georg Brandl61fdd712008-02-02 11:05:00 +000016
17import test.test_support
Antoine Pitrou8aea0502009-10-27 21:27:24 +000018from test.test_support import reap_children, reap_threads, verbose
Victor Stinner6a102812010-04-27 23:55:59 +000019try:
20 import threading
21except ImportError:
22 threading = None
Georg Brandl61fdd712008-02-02 11:05:00 +000023
24test.test_support.requires("network")
Guido van Rossum39f1b362001-07-10 11:52:38 +000025
Georg Brandl61fdd712008-02-02 11:05:00 +000026TEST_STR = "hello world\n"
Trent Nelsone41b0062008-04-08 23:47:30 +000027HOST = test.test_support.HOST
Georg Brandl61fdd712008-02-02 11:05:00 +000028
29HAVE_UNIX_SOCKETS = hasattr(socket, "AF_UNIX")
Serhiy Storchaka32e23e72013-11-03 23:15:46 +020030requires_unix_sockets = unittest.skipUnless(HAVE_UNIX_SOCKETS,
31 'requires Unix sockets')
Georg Brandl61fdd712008-02-02 11:05:00 +000032HAVE_FORKING = hasattr(os, "fork") and os.name != "os2"
Serhiy Storchaka32e23e72013-11-03 23:15:46 +020033requires_forking = unittest.skipUnless(HAVE_FORKING, 'requires forking')
Georg Brandl61fdd712008-02-02 11:05:00 +000034
Jeffrey Yasskinf28896d2008-03-05 06:19:56 +000035def signal_alarm(n):
36 """Call signal.alarm when it exists (i.e. not on Windows)."""
37 if hasattr(signal, 'alarm'):
38 signal.alarm(n)
Guido van Rossum39f1b362001-07-10 11:52:38 +000039
Antoine Pitrou467a5c42012-04-09 01:15:06 +020040# Remember real select() to avoid interferences with mocking
41_real_select = select.select
42
Guido van Rossum39f1b362001-07-10 11:52:38 +000043def receive(sock, n, timeout=20):
Antoine Pitrou467a5c42012-04-09 01:15:06 +020044 r, w, x = _real_select([sock], [], [], timeout)
Guido van Rossum39f1b362001-07-10 11:52:38 +000045 if sock in r:
46 return sock.recv(n)
47 else:
Walter Dörwald70a6b492004-02-12 17:35:32 +000048 raise RuntimeError, "timed out on %r" % (sock,)
Guido van Rossum39f1b362001-07-10 11:52:38 +000049
Amaury Forgeot d'Arc72a65762008-02-03 23:57:24 +000050if HAVE_UNIX_SOCKETS:
Georg Brandle152a772008-05-24 18:31:28 +000051 class ForkingUnixStreamServer(SocketServer.ForkingMixIn,
52 SocketServer.UnixStreamServer):
Amaury Forgeot d'Arc72a65762008-02-03 23:57:24 +000053 pass
Georg Brandl61fdd712008-02-02 11:05:00 +000054
Georg Brandle152a772008-05-24 18:31:28 +000055 class ForkingUnixDatagramServer(SocketServer.ForkingMixIn,
56 SocketServer.UnixDatagramServer):
Amaury Forgeot d'Arc72a65762008-02-03 23:57:24 +000057 pass
Georg Brandl61fdd712008-02-02 11:05:00 +000058
59
Jeffrey Yasskin392c1592008-02-28 18:03:15 +000060@contextlib.contextmanager
61def simple_subprocess(testcase):
62 pid = os.fork()
63 if pid == 0:
Andrew Svetlov4bb142b2012-12-18 21:27:37 +020064 # Don't raise an exception; it would be caught by the test harness.
Jeffrey Yasskin392c1592008-02-28 18:03:15 +000065 os._exit(72)
66 yield None
67 pid2, status = os.waitpid(pid, 0)
Ezio Melotti2623a372010-11-21 13:34:58 +000068 testcase.assertEqual(pid2, pid)
69 testcase.assertEqual(72 << 8, status)
Jeffrey Yasskin392c1592008-02-28 18:03:15 +000070
71
Victor Stinnerb4920d52017-09-27 03:02:57 -070072def close_server(server):
73 server.server_close()
74
75 if hasattr(server, 'active_children'):
76 # ForkingMixIn: Manually reap all child processes, since server_close()
77 # calls waitpid() in non-blocking mode using the WNOHANG flag.
78 for pid in server.active_children.copy():
79 try:
80 os.waitpid(pid, 0)
81 except ChildProcessError:
82 pass
83 server.active_children.clear()
84
85
Victor Stinner708c0722010-05-26 17:25:28 +000086@unittest.skipUnless(threading, 'Threading required for this test.')
Georg Brandl61fdd712008-02-02 11:05:00 +000087class SocketServerTest(unittest.TestCase):
88 """Test all socket servers."""
Guido van Rossum39f1b362001-07-10 11:52:38 +000089
Georg Brandl61fdd712008-02-02 11:05:00 +000090 def setUp(self):
Victor Stinner3604b232018-06-01 15:23:02 +020091 self.addCleanup(signal_alarm, 0)
Victor Stinnerb30ac942011-07-14 14:53:24 +020092 signal_alarm(60) # Kill deadlocks after 60 seconds.
Georg Brandl61fdd712008-02-02 11:05:00 +000093 self.port_seed = 0
94 self.test_files = []
Neal Norwitzb476fdf2006-08-15 04:58:28 +000095
Georg Brandl61fdd712008-02-02 11:05:00 +000096 def tearDown(self):
Victor Stinner3604b232018-06-01 15:23:02 +020097 self.doCleanups()
Georg Brandl61fdd712008-02-02 11:05:00 +000098 reap_children()
99
100 for fn in self.test_files:
101 try:
102 os.remove(fn)
103 except os.error:
104 pass
105 self.test_files[:] = []
Georg Brandl61fdd712008-02-02 11:05:00 +0000106
107 def pickaddr(self, proto):
108 if proto == socket.AF_INET:
Jeffrey Yasskin180997b2008-02-28 05:53:18 +0000109 return (HOST, 0)
Georg Brandl61fdd712008-02-02 11:05:00 +0000110 else:
Jeffrey Yasskin180997b2008-02-28 05:53:18 +0000111 # XXX: We need a way to tell AF_UNIX to pick its own name
112 # like AF_INET provides port==0.
113 dir = None
114 if os.name == 'os2':
115 dir = '\socket'
116 fn = tempfile.mktemp(prefix='unix_socket.', dir=dir)
Georg Brandl61fdd712008-02-02 11:05:00 +0000117 if os.name == 'os2':
118 # AF_UNIX socket names on OS/2 require a specific prefix
119 # which can't include a drive letter and must also use
120 # backslashes as directory separators
121 if fn[1] == ':':
122 fn = fn[2:]
123 if fn[0] in (os.sep, os.altsep):
124 fn = fn[1:]
Georg Brandl61fdd712008-02-02 11:05:00 +0000125 if os.sep == '/':
126 fn = fn.replace(os.sep, os.altsep)
127 else:
128 fn = fn.replace(os.altsep, os.sep)
129 self.test_files.append(fn)
130 return fn
131
Jeffrey Yasskine75f59a2008-03-07 06:22:15 +0000132 def make_server(self, addr, svrcls, hdlrbase):
133 class MyServer(svrcls):
134 def handle_error(self, request, client_address):
135 self.close_request(request)
Victor Stinnerb4920d52017-09-27 03:02:57 -0700136 close_server(self)
Jeffrey Yasskine75f59a2008-03-07 06:22:15 +0000137 raise
138
Jeffrey Yasskin180997b2008-02-28 05:53:18 +0000139 class MyHandler(hdlrbase):
140 def handle(self):
141 line = self.rfile.readline()
142 self.wfile.write(line)
143
Jeffrey Yasskine75f59a2008-03-07 06:22:15 +0000144 if verbose: print "creating server"
145 server = MyServer(addr, MyHandler)
Ezio Melotti2623a372010-11-21 13:34:58 +0000146 self.assertEqual(server.server_address, server.socket.getsockname())
Jeffrey Yasskine75f59a2008-03-07 06:22:15 +0000147 return server
148
Antoine Pitrou8aea0502009-10-27 21:27:24 +0000149 @reap_threads
Jeffrey Yasskine75f59a2008-03-07 06:22:15 +0000150 def run_server(self, svrcls, hdlrbase, testfunc):
151 server = self.make_server(self.pickaddr(svrcls.address_family),
152 svrcls, hdlrbase)
153 # We had the OS pick a port, so pull the real address out of
154 # the server.
155 addr = server.server_address
Jeffrey Yasskin180997b2008-02-28 05:53:18 +0000156 if verbose:
Jeffrey Yasskine75f59a2008-03-07 06:22:15 +0000157 print "server created"
Jeffrey Yasskin180997b2008-02-28 05:53:18 +0000158 print "ADDR =", addr
159 print "CLASS =", svrcls
Jeffrey Yasskine75f59a2008-03-07 06:22:15 +0000160 t = threading.Thread(
161 name='%s serving' % svrcls,
162 target=server.serve_forever,
163 # Short poll interval to make the test finish quickly.
164 # Time between requests is short enough that we won't wake
165 # up spuriously too many times.
166 kwargs={'poll_interval':0.01})
Benjamin Petersona9b22222008-08-18 18:01:43 +0000167 t.daemon = True # In case this function raises.
Jeffrey Yasskin180997b2008-02-28 05:53:18 +0000168 t.start()
169 if verbose: print "server running"
Jeffrey Yasskine75f59a2008-03-07 06:22:15 +0000170 for i in range(3):
Jeffrey Yasskin180997b2008-02-28 05:53:18 +0000171 if verbose: print "test client", i
172 testfunc(svrcls.address_family, addr)
173 if verbose: print "waiting for server"
Jeffrey Yasskine75f59a2008-03-07 06:22:15 +0000174 server.shutdown()
Jeffrey Yasskin180997b2008-02-28 05:53:18 +0000175 t.join()
Victor Stinnerb4920d52017-09-27 03:02:57 -0700176 close_server(server)
Robert Collins2f2c8292015-07-29 12:48:42 +1200177 self.assertRaises(socket.error, server.socket.fileno)
Jeffrey Yasskin180997b2008-02-28 05:53:18 +0000178 if verbose: print "done"
Georg Brandl61fdd712008-02-02 11:05:00 +0000179
180 def stream_examine(self, proto, addr):
181 s = socket.socket(proto, socket.SOCK_STREAM)
182 s.connect(addr)
183 s.sendall(TEST_STR)
184 buf = data = receive(s, 100)
185 while data and '\n' not in buf:
186 data = receive(s, 100)
187 buf += data
Ezio Melotti2623a372010-11-21 13:34:58 +0000188 self.assertEqual(buf, TEST_STR)
Georg Brandl61fdd712008-02-02 11:05:00 +0000189 s.close()
190
191 def dgram_examine(self, proto, addr):
192 s = socket.socket(proto, socket.SOCK_DGRAM)
Martin Panter098f6d02016-02-24 04:45:33 +0000193 if HAVE_UNIX_SOCKETS and proto == socket.AF_UNIX:
194 s.bind(self.pickaddr(proto))
Georg Brandl61fdd712008-02-02 11:05:00 +0000195 s.sendto(TEST_STR, addr)
196 buf = data = receive(s, 100)
197 while data and '\n' not in buf:
198 data = receive(s, 100)
199 buf += data
Ezio Melotti2623a372010-11-21 13:34:58 +0000200 self.assertEqual(buf, TEST_STR)
Georg Brandl61fdd712008-02-02 11:05:00 +0000201 s.close()
202
Jeffrey Yasskin180997b2008-02-28 05:53:18 +0000203 def test_TCPServer(self):
Georg Brandle152a772008-05-24 18:31:28 +0000204 self.run_server(SocketServer.TCPServer,
205 SocketServer.StreamRequestHandler,
Jeffrey Yasskin180997b2008-02-28 05:53:18 +0000206 self.stream_examine)
Georg Brandl61fdd712008-02-02 11:05:00 +0000207
Jeffrey Yasskin180997b2008-02-28 05:53:18 +0000208 def test_ThreadingTCPServer(self):
Georg Brandle152a772008-05-24 18:31:28 +0000209 self.run_server(SocketServer.ThreadingTCPServer,
210 SocketServer.StreamRequestHandler,
Jeffrey Yasskin180997b2008-02-28 05:53:18 +0000211 self.stream_examine)
Georg Brandl61fdd712008-02-02 11:05:00 +0000212
Serhiy Storchaka32e23e72013-11-03 23:15:46 +0200213 @requires_forking
214 def test_ForkingTCPServer(self):
215 with simple_subprocess(self):
216 self.run_server(SocketServer.ForkingTCPServer,
Georg Brandle152a772008-05-24 18:31:28 +0000217 SocketServer.StreamRequestHandler,
Jeffrey Yasskin180997b2008-02-28 05:53:18 +0000218 self.stream_examine)
219
Serhiy Storchaka32e23e72013-11-03 23:15:46 +0200220 @requires_unix_sockets
221 def test_UnixStreamServer(self):
222 self.run_server(SocketServer.UnixStreamServer,
223 SocketServer.StreamRequestHandler,
224 self.stream_examine)
225
226 @requires_unix_sockets
227 def test_ThreadingUnixStreamServer(self):
228 self.run_server(SocketServer.ThreadingUnixStreamServer,
229 SocketServer.StreamRequestHandler,
230 self.stream_examine)
231
232 @requires_unix_sockets
233 @requires_forking
234 def test_ForkingUnixStreamServer(self):
235 with simple_subprocess(self):
236 self.run_server(ForkingUnixStreamServer,
Georg Brandle152a772008-05-24 18:31:28 +0000237 SocketServer.StreamRequestHandler,
Jeffrey Yasskin180997b2008-02-28 05:53:18 +0000238 self.stream_examine)
239
Jeffrey Yasskin180997b2008-02-28 05:53:18 +0000240 def test_UDPServer(self):
Georg Brandle152a772008-05-24 18:31:28 +0000241 self.run_server(SocketServer.UDPServer,
242 SocketServer.DatagramRequestHandler,
Jeffrey Yasskin180997b2008-02-28 05:53:18 +0000243 self.dgram_examine)
244
245 def test_ThreadingUDPServer(self):
Georg Brandle152a772008-05-24 18:31:28 +0000246 self.run_server(SocketServer.ThreadingUDPServer,
247 SocketServer.DatagramRequestHandler,
Jeffrey Yasskin180997b2008-02-28 05:53:18 +0000248 self.dgram_examine)
249
Serhiy Storchaka32e23e72013-11-03 23:15:46 +0200250 @requires_forking
251 def test_ForkingUDPServer(self):
252 with simple_subprocess(self):
253 self.run_server(SocketServer.ForkingUDPServer,
254 SocketServer.DatagramRequestHandler,
255 self.dgram_examine)
Georg Brandl61fdd712008-02-02 11:05:00 +0000256
Antoine Pitroufa1d8412012-04-09 00:47:24 +0200257 @contextlib.contextmanager
258 def mocked_select_module(self):
259 """Mocks the select.select() call to raise EINTR for first call"""
260 old_select = select.select
261
262 class MockSelect:
263 def __init__(self):
264 self.called = 0
265
266 def __call__(self, *args):
267 self.called += 1
268 if self.called == 1:
269 # raise the exception on first call
Antoine Pitroub5588c32012-04-09 01:41:34 +0200270 raise select.error(errno.EINTR, os.strerror(errno.EINTR))
Antoine Pitroufa1d8412012-04-09 00:47:24 +0200271 else:
272 # Return real select value for consecutive calls
273 return old_select(*args)
274
275 select.select = MockSelect()
276 try:
277 yield select.select
278 finally:
279 select.select = old_select
280
281 def test_InterruptServerSelectCall(self):
282 with self.mocked_select_module() as mock_select:
283 pid = self.run_server(SocketServer.TCPServer,
284 SocketServer.StreamRequestHandler,
285 self.stream_examine)
286 # Make sure select was called again:
287 self.assertGreater(mock_select.called, 1)
288
Martin Panter098f6d02016-02-24 04:45:33 +0000289 @requires_unix_sockets
290 def test_UnixDatagramServer(self):
291 self.run_server(SocketServer.UnixDatagramServer,
292 SocketServer.DatagramRequestHandler,
293 self.dgram_examine)
Georg Brandl61fdd712008-02-02 11:05:00 +0000294
Martin Panter098f6d02016-02-24 04:45:33 +0000295 @requires_unix_sockets
296 def test_ThreadingUnixDatagramServer(self):
297 self.run_server(SocketServer.ThreadingUnixDatagramServer,
298 SocketServer.DatagramRequestHandler,
299 self.dgram_examine)
300
301 @requires_unix_sockets
302 @requires_forking
303 def test_ForkingUnixDatagramServer(self):
304 self.run_server(ForkingUnixDatagramServer,
305 SocketServer.DatagramRequestHandler,
306 self.dgram_examine)
Georg Brandl61fdd712008-02-02 11:05:00 +0000307
Antoine Pitroua6240402010-04-25 21:40:32 +0000308 @reap_threads
309 def test_shutdown(self):
310 # Issue #2302: shutdown() should always succeed in making an
311 # other thread leave serve_forever().
312 class MyServer(SocketServer.TCPServer):
313 pass
314
315 class MyHandler(SocketServer.StreamRequestHandler):
316 pass
317
318 threads = []
319 for i in range(20):
320 s = MyServer((HOST, 0), MyHandler)
321 t = threading.Thread(
322 name='MyServer serving',
323 target=s.serve_forever,
324 kwargs={'poll_interval':0.01})
325 t.daemon = True # In case this function raises.
326 threads.append((t, s))
327 for t, s in threads:
328 t.start()
329 s.shutdown()
330 for t, s in threads:
331 t.join()
Victor Stinnerb4920d52017-09-27 03:02:57 -0700332 close_server(s)
Antoine Pitroua6240402010-04-25 21:40:32 +0000333
Charles-François Natali977c4242014-10-13 18:39:34 +0100334 def test_tcpserver_bind_leak(self):
335 # Issue #22435: the server socket wouldn't be closed if bind()/listen()
336 # failed.
337 # Create many servers for which bind() will fail, to see if this result
338 # in FD exhaustion.
339 for i in range(1024):
340 with self.assertRaises(OverflowError):
341 SocketServer.TCPServer((HOST, -1),
342 SocketServer.StreamRequestHandler)
343
Martin Panter63d1f472016-02-19 02:16:42 +0000344
345class MiscTestCase(unittest.TestCase):
346
Martin Panterba8474b2016-02-18 10:43:55 +0000347 def test_shutdown_request_called_if_verify_request_false(self):
348 # Issue #26309: BaseServer should call shutdown_request even if
349 # verify_request is False
Martin Panterba8474b2016-02-18 10:43:55 +0000350
351 class MyServer(SocketServer.TCPServer):
352 def verify_request(self, request, client_address):
353 return False
354
Martin Panter63d1f472016-02-19 02:16:42 +0000355 shutdown_called = 0
Martin Panterba8474b2016-02-18 10:43:55 +0000356 def shutdown_request(self, request):
Martin Panter63d1f472016-02-19 02:16:42 +0000357 self.shutdown_called += 1
Martin Panterba8474b2016-02-18 10:43:55 +0000358 SocketServer.TCPServer.shutdown_request(self, request)
359
Martin Panter63d1f472016-02-19 02:16:42 +0000360 server = MyServer((HOST, 0), SocketServer.StreamRequestHandler)
361 s = socket.socket(server.address_family, socket.SOCK_STREAM)
362 s.connect(server.server_address)
363 s.close()
364 server.handle_request()
365 self.assertEqual(server.shutdown_called, 1)
Victor Stinnerb4920d52017-09-27 03:02:57 -0700366 close_server(server)
Martin Panterba8474b2016-02-18 10:43:55 +0000367
Guido van Rossum39f1b362001-07-10 11:52:38 +0000368
Tim Petersa9f6f222001-09-17 23:56:20 +0000369def test_main():
Tim Petersa9f6f222001-09-17 23:56:20 +0000370 if imp.lock_held():
Georg Brandl61fdd712008-02-02 11:05:00 +0000371 # If the import lock is held, the threads will hang
Benjamin Petersonbec087f2009-03-26 21:10:30 +0000372 raise unittest.SkipTest("can't run when import lock is held")
Tim Petersa9f6f222001-09-17 23:56:20 +0000373
Georg Brandl61fdd712008-02-02 11:05:00 +0000374 test.test_support.run_unittest(SocketServerTest)
Guido van Rossum39f1b362001-07-10 11:52:38 +0000375
Tim Petersa9f6f222001-09-17 23:56:20 +0000376if __name__ == "__main__":
377 test_main()