blob: 9a907292aa74df04340fc84d3243d6410eded8a2 [file] [log] [blame]
Christian Heimes292d3512008-02-03 16:51:08 +00001"""
Alexandre Vassalottice261952008-05-12 02:31:37 +00002Test suite for socketserver.
Christian Heimes292d3512008-02-03 16:51:08 +00003"""
Guido van Rossum39f1b362001-07-10 11:52:38 +00004
Christian Heimes70e7ea22008-02-28 20:02:27 +00005import contextlib
Christian Heimes9e7f1d22008-02-28 12:27:11 +00006import os
Guido van Rossum39f1b362001-07-10 11:52:38 +00007import select
Christian Heimes9e7f1d22008-02-28 12:27:11 +00008import signal
9import socket
10import tempfile
Christian Heimes292d3512008-02-03 16:51:08 +000011import unittest
Alexandre Vassalottice261952008-05-12 02:31:37 +000012import socketserver
Christian Heimes292d3512008-02-03 16:51:08 +000013
Benjamin Petersonee8712c2008-05-20 21:35:26 +000014import test.support
Antoine Pitrouc00d4b42009-10-27 21:32:38 +000015from test.support import reap_children, reap_threads, verbose
Victor Stinner45df8202010-04-28 22:31:17 +000016try:
17 import threading
18except ImportError:
19 threading = None
Christian Heimes292d3512008-02-03 16:51:08 +000020
Benjamin Petersonee8712c2008-05-20 21:35:26 +000021test.support.requires("network")
Guido van Rossum39f1b362001-07-10 11:52:38 +000022
Christian Heimes292d3512008-02-03 16:51:08 +000023TEST_STR = b"hello world\n"
Benjamin Petersonee8712c2008-05-20 21:35:26 +000024HOST = test.support.HOST
Christian Heimes292d3512008-02-03 16:51:08 +000025
26HAVE_UNIX_SOCKETS = hasattr(socket, "AF_UNIX")
Serhiy Storchaka43767632013-11-03 21:31:38 +020027requires_unix_sockets = unittest.skipUnless(HAVE_UNIX_SOCKETS,
28 'requires Unix sockets')
Jesus Ceaf1af7052012-10-05 02:48:46 +020029HAVE_FORKING = hasattr(os, "fork")
Serhiy Storchaka43767632013-11-03 21:31:38 +020030requires_forking = unittest.skipUnless(HAVE_FORKING, 'requires forking')
Christian Heimes292d3512008-02-03 16:51:08 +000031
Christian Heimesdd15f6c2008-03-16 00:07:10 +000032def signal_alarm(n):
33 """Call signal.alarm when it exists (i.e. not on Windows)."""
34 if hasattr(signal, 'alarm'):
35 signal.alarm(n)
Guido van Rossum39f1b362001-07-10 11:52:38 +000036
Antoine Pitrouf18d6f32012-04-09 01:16:47 +020037# Remember real select() to avoid interferences with mocking
38_real_select = select.select
39
Christian Heimes292d3512008-02-03 16:51:08 +000040def receive(sock, n, timeout=20):
Antoine Pitrouf18d6f32012-04-09 01:16:47 +020041 r, w, x = _real_select([sock], [], [], timeout)
Christian Heimes292d3512008-02-03 16:51:08 +000042 if sock in r:
43 return sock.recv(n)
44 else:
45 raise RuntimeError("timed out on %r" % (sock,))
46
Gregory P. Smith ext:(%20%5BGoogle%20Inc.%5D)a9459692016-06-03 05:26:14 +000047if HAVE_UNIX_SOCKETS and HAVE_FORKING:
Alexandre Vassalottice261952008-05-12 02:31:37 +000048 class ForkingUnixStreamServer(socketserver.ForkingMixIn,
49 socketserver.UnixStreamServer):
Christian Heimes15ebc882008-02-04 18:48:49 +000050 pass
Christian Heimes292d3512008-02-03 16:51:08 +000051
Alexandre Vassalottice261952008-05-12 02:31:37 +000052 class ForkingUnixDatagramServer(socketserver.ForkingMixIn,
53 socketserver.UnixDatagramServer):
Christian Heimes15ebc882008-02-04 18:48:49 +000054 pass
Christian Heimes292d3512008-02-03 16:51:08 +000055
56
Christian Heimes70e7ea22008-02-28 20:02:27 +000057@contextlib.contextmanager
58def simple_subprocess(testcase):
Martin Panterd9108d12016-02-21 08:49:56 +000059 """Tests that a custom child process is not waited on (Issue 1540386)"""
Christian Heimes70e7ea22008-02-28 20:02:27 +000060 pid = os.fork()
61 if pid == 0:
Andrew Svetlov737fb892012-12-18 21:14:22 +020062 # Don't raise an exception; it would be caught by the test harness.
Christian Heimes70e7ea22008-02-28 20:02:27 +000063 os._exit(72)
64 yield None
65 pid2, status = os.waitpid(pid, 0)
Ezio Melottib3aedd42010-11-20 19:04:17 +000066 testcase.assertEqual(pid2, pid)
67 testcase.assertEqual(72 << 8, status)
Christian Heimes70e7ea22008-02-28 20:02:27 +000068
69
Victor Stinner5f22e722010-05-26 17:33:03 +000070@unittest.skipUnless(threading, 'Threading required for this test.')
Christian Heimes292d3512008-02-03 16:51:08 +000071class SocketServerTest(unittest.TestCase):
72 """Test all socket servers."""
Guido van Rossum39f1b362001-07-10 11:52:38 +000073
Christian Heimes292d3512008-02-03 16:51:08 +000074 def setUp(self):
Victor Stinner5702ae62011-07-14 14:53:24 +020075 signal_alarm(60) # Kill deadlocks after 60 seconds.
Christian Heimes292d3512008-02-03 16:51:08 +000076 self.port_seed = 0
77 self.test_files = []
Guido van Rossum39f1b362001-07-10 11:52:38 +000078
Christian Heimes292d3512008-02-03 16:51:08 +000079 def tearDown(self):
Christian Heimesfe337bf2008-03-23 21:54:12 +000080 signal_alarm(0) # Didn't deadlock.
Christian Heimes292d3512008-02-03 16:51:08 +000081 reap_children()
Thomas Wouters00ee7ba2006-08-21 19:07:27 +000082
Christian Heimes292d3512008-02-03 16:51:08 +000083 for fn in self.test_files:
84 try:
85 os.remove(fn)
Andrew Svetlovad28c7f2012-12-18 22:02:39 +020086 except OSError:
Christian Heimes292d3512008-02-03 16:51:08 +000087 pass
88 self.test_files[:] = []
Christian Heimes292d3512008-02-03 16:51:08 +000089
90 def pickaddr(self, proto):
91 if proto == socket.AF_INET:
Christian Heimes9e7f1d22008-02-28 12:27:11 +000092 return (HOST, 0)
Christian Heimes292d3512008-02-03 16:51:08 +000093 else:
Christian Heimes9e7f1d22008-02-28 12:27:11 +000094 # XXX: We need a way to tell AF_UNIX to pick its own name
95 # like AF_INET provides port==0.
96 dir = None
Christian Heimes9e7f1d22008-02-28 12:27:11 +000097 fn = tempfile.mktemp(prefix='unix_socket.', dir=dir)
Christian Heimes292d3512008-02-03 16:51:08 +000098 self.test_files.append(fn)
99 return fn
100
Christian Heimesdd15f6c2008-03-16 00:07:10 +0000101 def make_server(self, addr, svrcls, hdlrbase):
102 class MyServer(svrcls):
103 def handle_error(self, request, client_address):
104 self.close_request(request)
Christian Heimesdd15f6c2008-03-16 00:07:10 +0000105 raise
Christian Heimes9e7f1d22008-02-28 12:27:11 +0000106
Christian Heimes9e7f1d22008-02-28 12:27:11 +0000107 class MyHandler(hdlrbase):
108 def handle(self):
109 line = self.rfile.readline()
110 self.wfile.write(line)
111
Christian Heimesdd15f6c2008-03-16 00:07:10 +0000112 if verbose: print("creating server")
113 server = MyServer(addr, MyHandler)
Ezio Melottib3aedd42010-11-20 19:04:17 +0000114 self.assertEqual(server.server_address, server.socket.getsockname())
Christian Heimesdd15f6c2008-03-16 00:07:10 +0000115 return server
116
Antoine Pitrouc00d4b42009-10-27 21:32:38 +0000117 @reap_threads
Christian Heimesdd15f6c2008-03-16 00:07:10 +0000118 def run_server(self, svrcls, hdlrbase, testfunc):
119 server = self.make_server(self.pickaddr(svrcls.address_family),
120 svrcls, hdlrbase)
121 # We had the OS pick a port, so pull the real address out of
122 # the server.
123 addr = server.server_address
Christian Heimes9e7f1d22008-02-28 12:27:11 +0000124 if verbose:
125 print("ADDR =", addr)
126 print("CLASS =", svrcls)
Christian Heimesdd15f6c2008-03-16 00:07:10 +0000127
128 t = threading.Thread(
129 name='%s serving' % svrcls,
130 target=server.serve_forever,
131 # Short poll interval to make the test finish quickly.
132 # Time between requests is short enough that we won't wake
133 # up spuriously too many times.
134 kwargs={'poll_interval':0.01})
Benjamin Peterson72753702008-08-18 18:09:21 +0000135 t.daemon = True # In case this function raises.
Christian Heimes9e7f1d22008-02-28 12:27:11 +0000136 t.start()
137 if verbose: print("server running")
Christian Heimesdd15f6c2008-03-16 00:07:10 +0000138 for i in range(3):
Christian Heimes9e7f1d22008-02-28 12:27:11 +0000139 if verbose: print("test client", i)
140 testfunc(svrcls.address_family, addr)
141 if verbose: print("waiting for server")
Christian Heimesdd15f6c2008-03-16 00:07:10 +0000142 server.shutdown()
Christian Heimes9e7f1d22008-02-28 12:27:11 +0000143 t.join()
Victor Stinner109761b2011-01-03 14:30:39 +0000144 server.server_close()
Robert Collins1ee92832015-07-29 12:52:40 +1200145 self.assertEqual(-1, server.socket.fileno())
Christian Heimes9e7f1d22008-02-28 12:27:11 +0000146 if verbose: print("done")
Christian Heimes292d3512008-02-03 16:51:08 +0000147
148 def stream_examine(self, proto, addr):
149 s = socket.socket(proto, socket.SOCK_STREAM)
150 s.connect(addr)
151 s.sendall(TEST_STR)
152 buf = data = receive(s, 100)
Christian Heimesfdb6bb52008-02-03 17:32:13 +0000153 while data and b'\n' not in buf:
Christian Heimes292d3512008-02-03 16:51:08 +0000154 data = receive(s, 100)
155 buf += data
Ezio Melottib3aedd42010-11-20 19:04:17 +0000156 self.assertEqual(buf, TEST_STR)
Christian Heimes292d3512008-02-03 16:51:08 +0000157 s.close()
158
159 def dgram_examine(self, proto, addr):
160 s = socket.socket(proto, socket.SOCK_DGRAM)
Martin Panter1827eff2016-02-24 05:12:59 +0000161 if HAVE_UNIX_SOCKETS and proto == socket.AF_UNIX:
162 s.bind(self.pickaddr(proto))
Christian Heimes292d3512008-02-03 16:51:08 +0000163 s.sendto(TEST_STR, addr)
164 buf = data = receive(s, 100)
Christian Heimesfdb6bb52008-02-03 17:32:13 +0000165 while data and b'\n' not in buf:
Christian Heimes292d3512008-02-03 16:51:08 +0000166 data = receive(s, 100)
167 buf += data
Ezio Melottib3aedd42010-11-20 19:04:17 +0000168 self.assertEqual(buf, TEST_STR)
Christian Heimes292d3512008-02-03 16:51:08 +0000169 s.close()
170
Christian Heimes9e7f1d22008-02-28 12:27:11 +0000171 def test_TCPServer(self):
Alexandre Vassalottice261952008-05-12 02:31:37 +0000172 self.run_server(socketserver.TCPServer,
173 socketserver.StreamRequestHandler,
Christian Heimes9e7f1d22008-02-28 12:27:11 +0000174 self.stream_examine)
Christian Heimes292d3512008-02-03 16:51:08 +0000175
Christian Heimes9e7f1d22008-02-28 12:27:11 +0000176 def test_ThreadingTCPServer(self):
Alexandre Vassalottice261952008-05-12 02:31:37 +0000177 self.run_server(socketserver.ThreadingTCPServer,
178 socketserver.StreamRequestHandler,
Christian Heimes9e7f1d22008-02-28 12:27:11 +0000179 self.stream_examine)
Christian Heimes292d3512008-02-03 16:51:08 +0000180
Serhiy Storchaka43767632013-11-03 21:31:38 +0200181 @requires_forking
182 def test_ForkingTCPServer(self):
183 with simple_subprocess(self):
184 self.run_server(socketserver.ForkingTCPServer,
Alexandre Vassalottice261952008-05-12 02:31:37 +0000185 socketserver.StreamRequestHandler,
Christian Heimes9e7f1d22008-02-28 12:27:11 +0000186 self.stream_examine)
187
Serhiy Storchaka43767632013-11-03 21:31:38 +0200188 @requires_unix_sockets
189 def test_UnixStreamServer(self):
190 self.run_server(socketserver.UnixStreamServer,
191 socketserver.StreamRequestHandler,
192 self.stream_examine)
193
194 @requires_unix_sockets
195 def test_ThreadingUnixStreamServer(self):
196 self.run_server(socketserver.ThreadingUnixStreamServer,
197 socketserver.StreamRequestHandler,
198 self.stream_examine)
199
200 @requires_unix_sockets
201 @requires_forking
202 def test_ForkingUnixStreamServer(self):
203 with simple_subprocess(self):
204 self.run_server(ForkingUnixStreamServer,
Alexandre Vassalottice261952008-05-12 02:31:37 +0000205 socketserver.StreamRequestHandler,
Christian Heimes9e7f1d22008-02-28 12:27:11 +0000206 self.stream_examine)
207
Christian Heimes9e7f1d22008-02-28 12:27:11 +0000208 def test_UDPServer(self):
Alexandre Vassalottice261952008-05-12 02:31:37 +0000209 self.run_server(socketserver.UDPServer,
210 socketserver.DatagramRequestHandler,
Christian Heimes9e7f1d22008-02-28 12:27:11 +0000211 self.dgram_examine)
212
213 def test_ThreadingUDPServer(self):
Alexandre Vassalottice261952008-05-12 02:31:37 +0000214 self.run_server(socketserver.ThreadingUDPServer,
215 socketserver.DatagramRequestHandler,
Christian Heimes9e7f1d22008-02-28 12:27:11 +0000216 self.dgram_examine)
217
Serhiy Storchaka43767632013-11-03 21:31:38 +0200218 @requires_forking
219 def test_ForkingUDPServer(self):
220 with simple_subprocess(self):
221 self.run_server(socketserver.ForkingUDPServer,
222 socketserver.DatagramRequestHandler,
223 self.dgram_examine)
Christian Heimes292d3512008-02-03 16:51:08 +0000224
Martin Panter1827eff2016-02-24 05:12:59 +0000225 @requires_unix_sockets
226 def test_UnixDatagramServer(self):
227 self.run_server(socketserver.UnixDatagramServer,
228 socketserver.DatagramRequestHandler,
229 self.dgram_examine)
Christian Heimes292d3512008-02-03 16:51:08 +0000230
Martin Panter1827eff2016-02-24 05:12:59 +0000231 @requires_unix_sockets
232 def test_ThreadingUnixDatagramServer(self):
233 self.run_server(socketserver.ThreadingUnixDatagramServer,
234 socketserver.DatagramRequestHandler,
235 self.dgram_examine)
236
237 @requires_unix_sockets
238 @requires_forking
239 def test_ForkingUnixDatagramServer(self):
240 self.run_server(ForkingUnixDatagramServer,
241 socketserver.DatagramRequestHandler,
242 self.dgram_examine)
Christian Heimes292d3512008-02-03 16:51:08 +0000243
Antoine Pitrou3bcba8e2010-04-25 22:01:43 +0000244 @reap_threads
245 def test_shutdown(self):
246 # Issue #2302: shutdown() should always succeed in making an
247 # other thread leave serve_forever().
248 class MyServer(socketserver.TCPServer):
249 pass
250
251 class MyHandler(socketserver.StreamRequestHandler):
252 pass
253
254 threads = []
255 for i in range(20):
256 s = MyServer((HOST, 0), MyHandler)
257 t = threading.Thread(
258 name='MyServer serving',
259 target=s.serve_forever,
260 kwargs={'poll_interval':0.01})
261 t.daemon = True # In case this function raises.
262 threads.append((t, s))
263 for t, s in threads:
264 t.start()
265 s.shutdown()
266 for t, s in threads:
267 t.join()
Victor Stinner109761b2011-01-03 14:30:39 +0000268 s.server_close()
Antoine Pitrou3bcba8e2010-04-25 22:01:43 +0000269
Charles-François Natali0f4f048f2014-10-13 19:19:26 +0100270 def test_tcpserver_bind_leak(self):
271 # Issue #22435: the server socket wouldn't be closed if bind()/listen()
272 # failed.
273 # Create many servers for which bind() will fail, to see if this result
274 # in FD exhaustion.
275 for i in range(1024):
276 with self.assertRaises(OverflowError):
277 socketserver.TCPServer((HOST, -1),
278 socketserver.StreamRequestHandler)
279
Martin Panter0cab9c12016-04-13 00:36:52 +0000280 def test_context_manager(self):
281 with socketserver.TCPServer((HOST, 0),
282 socketserver.StreamRequestHandler) as server:
283 pass
284 self.assertEqual(-1, server.socket.fileno())
285
Guido van Rossum39f1b362001-07-10 11:52:38 +0000286
Martin Panterd9108d12016-02-21 08:49:56 +0000287class ErrorHandlerTest(unittest.TestCase):
288 """Test that the servers pass normal exceptions from the handler to
289 handle_error(), and that exiting exceptions like SystemExit and
290 KeyboardInterrupt are not passed."""
291
292 def tearDown(self):
293 test.support.unlink(test.support.TESTFN)
294
295 def test_sync_handled(self):
296 BaseErrorTestServer(ValueError)
297 self.check_result(handled=True)
298
299 def test_sync_not_handled(self):
300 with self.assertRaises(SystemExit):
301 BaseErrorTestServer(SystemExit)
302 self.check_result(handled=False)
303
304 @unittest.skipUnless(threading, 'Threading required for this test.')
305 def test_threading_handled(self):
306 ThreadingErrorTestServer(ValueError)
307 self.check_result(handled=True)
308
309 @unittest.skipUnless(threading, 'Threading required for this test.')
310 def test_threading_not_handled(self):
311 ThreadingErrorTestServer(SystemExit)
312 self.check_result(handled=False)
313
314 @requires_forking
315 def test_forking_handled(self):
316 ForkingErrorTestServer(ValueError)
317 self.check_result(handled=True)
318
319 @requires_forking
320 def test_forking_not_handled(self):
321 ForkingErrorTestServer(SystemExit)
322 self.check_result(handled=False)
323
324 def check_result(self, handled):
325 with open(test.support.TESTFN) as log:
326 expected = 'Handler called\n' + 'Error handled\n' * handled
327 self.assertEqual(log.read(), expected)
328
329
330class BaseErrorTestServer(socketserver.TCPServer):
331 def __init__(self, exception):
332 self.exception = exception
333 super().__init__((HOST, 0), BadHandler)
334 with socket.create_connection(self.server_address):
335 pass
336 try:
337 self.handle_request()
338 finally:
339 self.server_close()
340 self.wait_done()
341
342 def handle_error(self, request, client_address):
343 with open(test.support.TESTFN, 'a') as log:
344 log.write('Error handled\n')
345
346 def wait_done(self):
347 pass
348
349
350class BadHandler(socketserver.BaseRequestHandler):
351 def handle(self):
352 with open(test.support.TESTFN, 'a') as log:
353 log.write('Handler called\n')
354 raise self.server.exception('Test error')
355
356
357class ThreadingErrorTestServer(socketserver.ThreadingMixIn,
358 BaseErrorTestServer):
359 def __init__(self, *pos, **kw):
360 self.done = threading.Event()
361 super().__init__(*pos, **kw)
362
363 def shutdown_request(self, *pos, **kw):
364 super().shutdown_request(*pos, **kw)
365 self.done.set()
366
367 def wait_done(self):
368 self.done.wait()
369
370
Gregory P. Smith ext:(%20%5BGoogle%20Inc.%5D)a9459692016-06-03 05:26:14 +0000371if HAVE_FORKING:
372 class ForkingErrorTestServer(socketserver.ForkingMixIn, BaseErrorTestServer):
373 def wait_done(self):
374 [child] = self.active_children
375 os.waitpid(child, 0)
376 self.active_children.clear()
Martin Panterd9108d12016-02-21 08:49:56 +0000377
378
Berker Peksag32653442015-02-03 11:55:09 +0200379class MiscTestCase(unittest.TestCase):
Tim Petersa9f6f222001-09-17 23:56:20 +0000380
Berker Peksag32653442015-02-03 11:55:09 +0200381 def test_all(self):
382 # objects defined in the module should be in __all__
383 expected = []
384 for name in dir(socketserver):
385 if not name.startswith('_'):
386 mod_object = getattr(socketserver, name)
387 if getattr(mod_object, '__module__', None) == 'socketserver':
388 expected.append(name)
389 self.assertCountEqual(socketserver.__all__, expected)
390
Martin Panter4bf42742016-02-19 02:16:42 +0000391 def test_shutdown_request_called_if_verify_request_false(self):
392 # Issue #26309: BaseServer should call shutdown_request even if
393 # verify_request is False
394
395 class MyServer(socketserver.TCPServer):
396 def verify_request(self, request, client_address):
397 return False
398
399 shutdown_called = 0
400 def shutdown_request(self, request):
401 self.shutdown_called += 1
402 socketserver.TCPServer.shutdown_request(self, request)
403
404 server = MyServer((HOST, 0), socketserver.StreamRequestHandler)
405 s = socket.socket(server.address_family, socket.SOCK_STREAM)
406 s.connect(server.server_address)
407 s.close()
408 server.handle_request()
409 self.assertEqual(server.shutdown_called, 1)
410 server.server_close()
411
Guido van Rossum39f1b362001-07-10 11:52:38 +0000412
Tim Petersa9f6f222001-09-17 23:56:20 +0000413if __name__ == "__main__":
Berker Peksag32653442015-02-03 11:55:09 +0200414 unittest.main()