blob: 07b0c193ea869c7ffbfcb952fd99c854982edcf5 [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")
30HAVE_FORKING = hasattr(os, "fork") and os.name != "os2"
31
Jeffrey Yasskinf28896d2008-03-05 06:19:56 +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
Guido van Rossum39f1b362001-07-10 11:52:38 +000037def receive(sock, n, timeout=20):
38 r, w, x = select.select([sock], [], [], timeout)
39 if sock in r:
40 return sock.recv(n)
41 else:
Walter Dörwald70a6b492004-02-12 17:35:32 +000042 raise RuntimeError, "timed out on %r" % (sock,)
Guido van Rossum39f1b362001-07-10 11:52:38 +000043
Amaury Forgeot d'Arc72a65762008-02-03 23:57:24 +000044if HAVE_UNIX_SOCKETS:
Georg Brandle152a772008-05-24 18:31:28 +000045 class ForkingUnixStreamServer(SocketServer.ForkingMixIn,
46 SocketServer.UnixStreamServer):
Amaury Forgeot d'Arc72a65762008-02-03 23:57:24 +000047 pass
Georg Brandl61fdd712008-02-02 11:05:00 +000048
Georg Brandle152a772008-05-24 18:31:28 +000049 class ForkingUnixDatagramServer(SocketServer.ForkingMixIn,
50 SocketServer.UnixDatagramServer):
Amaury Forgeot d'Arc72a65762008-02-03 23:57:24 +000051 pass
Georg Brandl61fdd712008-02-02 11:05:00 +000052
53
Jeffrey Yasskin392c1592008-02-28 18:03:15 +000054@contextlib.contextmanager
55def simple_subprocess(testcase):
56 pid = os.fork()
57 if pid == 0:
58 # Don't throw an exception; it would be caught by the test harness.
59 os._exit(72)
60 yield None
61 pid2, status = os.waitpid(pid, 0)
Ezio Melotti2623a372010-11-21 13:34:58 +000062 testcase.assertEqual(pid2, pid)
63 testcase.assertEqual(72 << 8, status)
Jeffrey Yasskin392c1592008-02-28 18:03:15 +000064
65
Victor Stinner708c0722010-05-26 17:25:28 +000066@unittest.skipUnless(threading, 'Threading required for this test.')
Georg Brandl61fdd712008-02-02 11:05:00 +000067class SocketServerTest(unittest.TestCase):
68 """Test all socket servers."""
Guido van Rossum39f1b362001-07-10 11:52:38 +000069
Georg Brandl61fdd712008-02-02 11:05:00 +000070 def setUp(self):
Victor Stinnerb30ac942011-07-14 14:53:24 +020071 signal_alarm(60) # Kill deadlocks after 60 seconds.
Georg Brandl61fdd712008-02-02 11:05:00 +000072 self.port_seed = 0
73 self.test_files = []
Neal Norwitzb476fdf2006-08-15 04:58:28 +000074
Georg Brandl61fdd712008-02-02 11:05:00 +000075 def tearDown(self):
Neal Norwitzacdb6fb2008-03-23 06:16:04 +000076 signal_alarm(0) # Didn't deadlock.
Georg Brandl61fdd712008-02-02 11:05:00 +000077 reap_children()
78
79 for fn in self.test_files:
80 try:
81 os.remove(fn)
82 except os.error:
83 pass
84 self.test_files[:] = []
Georg Brandl61fdd712008-02-02 11:05:00 +000085
86 def pickaddr(self, proto):
87 if proto == socket.AF_INET:
Jeffrey Yasskin180997b2008-02-28 05:53:18 +000088 return (HOST, 0)
Georg Brandl61fdd712008-02-02 11:05:00 +000089 else:
Jeffrey Yasskin180997b2008-02-28 05:53:18 +000090 # XXX: We need a way to tell AF_UNIX to pick its own name
91 # like AF_INET provides port==0.
92 dir = None
93 if os.name == 'os2':
94 dir = '\socket'
95 fn = tempfile.mktemp(prefix='unix_socket.', dir=dir)
Georg Brandl61fdd712008-02-02 11:05:00 +000096 if os.name == 'os2':
97 # AF_UNIX socket names on OS/2 require a specific prefix
98 # which can't include a drive letter and must also use
99 # backslashes as directory separators
100 if fn[1] == ':':
101 fn = fn[2:]
102 if fn[0] in (os.sep, os.altsep):
103 fn = fn[1:]
Georg Brandl61fdd712008-02-02 11:05:00 +0000104 if os.sep == '/':
105 fn = fn.replace(os.sep, os.altsep)
106 else:
107 fn = fn.replace(os.altsep, os.sep)
108 self.test_files.append(fn)
109 return fn
110
Jeffrey Yasskine75f59a2008-03-07 06:22:15 +0000111 def make_server(self, addr, svrcls, hdlrbase):
112 class MyServer(svrcls):
113 def handle_error(self, request, client_address):
114 self.close_request(request)
115 self.server_close()
116 raise
117
Jeffrey Yasskin180997b2008-02-28 05:53:18 +0000118 class MyHandler(hdlrbase):
119 def handle(self):
120 line = self.rfile.readline()
121 self.wfile.write(line)
122
Jeffrey Yasskine75f59a2008-03-07 06:22:15 +0000123 if verbose: print "creating server"
124 server = MyServer(addr, MyHandler)
Ezio Melotti2623a372010-11-21 13:34:58 +0000125 self.assertEqual(server.server_address, server.socket.getsockname())
Jeffrey Yasskine75f59a2008-03-07 06:22:15 +0000126 return server
127
Antoine Pitrou8aea0502009-10-27 21:27:24 +0000128 @reap_threads
Jeffrey Yasskine75f59a2008-03-07 06:22:15 +0000129 def run_server(self, svrcls, hdlrbase, testfunc):
130 server = self.make_server(self.pickaddr(svrcls.address_family),
131 svrcls, hdlrbase)
132 # We had the OS pick a port, so pull the real address out of
133 # the server.
134 addr = server.server_address
Jeffrey Yasskin180997b2008-02-28 05:53:18 +0000135 if verbose:
Jeffrey Yasskine75f59a2008-03-07 06:22:15 +0000136 print "server created"
Jeffrey Yasskin180997b2008-02-28 05:53:18 +0000137 print "ADDR =", addr
138 print "CLASS =", svrcls
Jeffrey Yasskine75f59a2008-03-07 06:22:15 +0000139 t = threading.Thread(
140 name='%s serving' % svrcls,
141 target=server.serve_forever,
142 # Short poll interval to make the test finish quickly.
143 # Time between requests is short enough that we won't wake
144 # up spuriously too many times.
145 kwargs={'poll_interval':0.01})
Benjamin Petersona9b22222008-08-18 18:01:43 +0000146 t.daemon = True # In case this function raises.
Jeffrey Yasskin180997b2008-02-28 05:53:18 +0000147 t.start()
148 if verbose: print "server running"
Jeffrey Yasskine75f59a2008-03-07 06:22:15 +0000149 for i in range(3):
Jeffrey Yasskin180997b2008-02-28 05:53:18 +0000150 if verbose: print "test client", i
151 testfunc(svrcls.address_family, addr)
152 if verbose: print "waiting for server"
Jeffrey Yasskine75f59a2008-03-07 06:22:15 +0000153 server.shutdown()
Jeffrey Yasskin180997b2008-02-28 05:53:18 +0000154 t.join()
155 if verbose: print "done"
Georg Brandl61fdd712008-02-02 11:05:00 +0000156
157 def stream_examine(self, proto, addr):
158 s = socket.socket(proto, socket.SOCK_STREAM)
159 s.connect(addr)
160 s.sendall(TEST_STR)
161 buf = data = receive(s, 100)
162 while data and '\n' not in buf:
163 data = receive(s, 100)
164 buf += data
Ezio Melotti2623a372010-11-21 13:34:58 +0000165 self.assertEqual(buf, TEST_STR)
Georg Brandl61fdd712008-02-02 11:05:00 +0000166 s.close()
167
168 def dgram_examine(self, proto, addr):
169 s = socket.socket(proto, socket.SOCK_DGRAM)
170 s.sendto(TEST_STR, addr)
171 buf = data = receive(s, 100)
172 while data and '\n' not in buf:
173 data = receive(s, 100)
174 buf += data
Ezio Melotti2623a372010-11-21 13:34:58 +0000175 self.assertEqual(buf, TEST_STR)
Georg Brandl61fdd712008-02-02 11:05:00 +0000176 s.close()
177
Jeffrey Yasskin180997b2008-02-28 05:53:18 +0000178 def test_TCPServer(self):
Georg Brandle152a772008-05-24 18:31:28 +0000179 self.run_server(SocketServer.TCPServer,
180 SocketServer.StreamRequestHandler,
Jeffrey Yasskin180997b2008-02-28 05:53:18 +0000181 self.stream_examine)
Georg Brandl61fdd712008-02-02 11:05:00 +0000182
Jeffrey Yasskin180997b2008-02-28 05:53:18 +0000183 def test_ThreadingTCPServer(self):
Georg Brandle152a772008-05-24 18:31:28 +0000184 self.run_server(SocketServer.ThreadingTCPServer,
185 SocketServer.StreamRequestHandler,
Jeffrey Yasskin180997b2008-02-28 05:53:18 +0000186 self.stream_examine)
Georg Brandl61fdd712008-02-02 11:05:00 +0000187
Jeffrey Yasskin180997b2008-02-28 05:53:18 +0000188 if HAVE_FORKING:
Jeffrey Yasskin392c1592008-02-28 18:03:15 +0000189 def test_ForkingTCPServer(self):
190 with simple_subprocess(self):
Georg Brandle152a772008-05-24 18:31:28 +0000191 self.run_server(SocketServer.ForkingTCPServer,
192 SocketServer.StreamRequestHandler,
Jeffrey Yasskin392c1592008-02-28 18:03:15 +0000193 self.stream_examine)
Jeffrey Yasskin180997b2008-02-28 05:53:18 +0000194
195 if HAVE_UNIX_SOCKETS:
196 def test_UnixStreamServer(self):
Georg Brandle152a772008-05-24 18:31:28 +0000197 self.run_server(SocketServer.UnixStreamServer,
198 SocketServer.StreamRequestHandler,
Jeffrey Yasskin180997b2008-02-28 05:53:18 +0000199 self.stream_examine)
200
201 def test_ThreadingUnixStreamServer(self):
Georg Brandle152a772008-05-24 18:31:28 +0000202 self.run_server(SocketServer.ThreadingUnixStreamServer,
203 SocketServer.StreamRequestHandler,
Jeffrey Yasskin180997b2008-02-28 05:53:18 +0000204 self.stream_examine)
205
Georg Brandl61fdd712008-02-02 11:05:00 +0000206 if HAVE_FORKING:
Jeffrey Yasskin180997b2008-02-28 05:53:18 +0000207 def test_ForkingUnixStreamServer(self):
Jeffrey Yasskin392c1592008-02-28 18:03:15 +0000208 with simple_subprocess(self):
209 self.run_server(ForkingUnixStreamServer,
Georg Brandle152a772008-05-24 18:31:28 +0000210 SocketServer.StreamRequestHandler,
Jeffrey Yasskin392c1592008-02-28 18:03:15 +0000211 self.stream_examine)
Jeffrey Yasskin180997b2008-02-28 05:53:18 +0000212
213 def test_UDPServer(self):
Georg Brandle152a772008-05-24 18:31:28 +0000214 self.run_server(SocketServer.UDPServer,
215 SocketServer.DatagramRequestHandler,
Jeffrey Yasskin180997b2008-02-28 05:53:18 +0000216 self.dgram_examine)
217
218 def test_ThreadingUDPServer(self):
Georg Brandle152a772008-05-24 18:31:28 +0000219 self.run_server(SocketServer.ThreadingUDPServer,
220 SocketServer.DatagramRequestHandler,
Jeffrey Yasskin180997b2008-02-28 05:53:18 +0000221 self.dgram_examine)
222
223 if HAVE_FORKING:
224 def test_ForkingUDPServer(self):
Jeffrey Yasskin392c1592008-02-28 18:03:15 +0000225 with simple_subprocess(self):
Georg Brandle152a772008-05-24 18:31:28 +0000226 self.run_server(SocketServer.ForkingUDPServer,
227 SocketServer.DatagramRequestHandler,
Jeffrey Yasskin392c1592008-02-28 18:03:15 +0000228 self.dgram_examine)
Georg Brandl61fdd712008-02-02 11:05:00 +0000229
Antoine Pitroufa1d8412012-04-09 00:47:24 +0200230 @contextlib.contextmanager
231 def mocked_select_module(self):
232 """Mocks the select.select() call to raise EINTR for first call"""
233 old_select = select.select
234
235 class MockSelect:
236 def __init__(self):
237 self.called = 0
238
239 def __call__(self, *args):
240 self.called += 1
241 if self.called == 1:
242 # raise the exception on first call
243 raise OSError(errno.EINTR, os.strerror(errno.EINTR))
244 else:
245 # Return real select value for consecutive calls
246 return old_select(*args)
247
248 select.select = MockSelect()
249 try:
250 yield select.select
251 finally:
252 select.select = old_select
253
254 def test_InterruptServerSelectCall(self):
255 with self.mocked_select_module() as mock_select:
256 pid = self.run_server(SocketServer.TCPServer,
257 SocketServer.StreamRequestHandler,
258 self.stream_examine)
259 # Make sure select was called again:
260 self.assertGreater(mock_select.called, 1)
261
Georg Brandl61fdd712008-02-02 11:05:00 +0000262 # Alas, on Linux (at least) recvfrom() doesn't return a meaningful
263 # client address so this cannot work:
264
Jeffrey Yasskin180997b2008-02-28 05:53:18 +0000265 # if HAVE_UNIX_SOCKETS:
266 # def test_UnixDatagramServer(self):
Georg Brandle152a772008-05-24 18:31:28 +0000267 # self.run_server(SocketServer.UnixDatagramServer,
268 # SocketServer.DatagramRequestHandler,
Jeffrey Yasskin180997b2008-02-28 05:53:18 +0000269 # self.dgram_examine)
270 #
271 # def test_ThreadingUnixDatagramServer(self):
Georg Brandle152a772008-05-24 18:31:28 +0000272 # self.run_server(SocketServer.ThreadingUnixDatagramServer,
273 # SocketServer.DatagramRequestHandler,
Jeffrey Yasskin180997b2008-02-28 05:53:18 +0000274 # self.dgram_examine)
275 #
Georg Brandl61fdd712008-02-02 11:05:00 +0000276 # if HAVE_FORKING:
Jeffrey Yasskin180997b2008-02-28 05:53:18 +0000277 # def test_ForkingUnixDatagramServer(self):
Georg Brandle152a772008-05-24 18:31:28 +0000278 # self.run_server(SocketServer.ForkingUnixDatagramServer,
279 # SocketServer.DatagramRequestHandler,
Jeffrey Yasskin180997b2008-02-28 05:53:18 +0000280 # self.dgram_examine)
Georg Brandl61fdd712008-02-02 11:05:00 +0000281
Antoine Pitroua6240402010-04-25 21:40:32 +0000282 @reap_threads
283 def test_shutdown(self):
284 # Issue #2302: shutdown() should always succeed in making an
285 # other thread leave serve_forever().
286 class MyServer(SocketServer.TCPServer):
287 pass
288
289 class MyHandler(SocketServer.StreamRequestHandler):
290 pass
291
292 threads = []
293 for i in range(20):
294 s = MyServer((HOST, 0), MyHandler)
295 t = threading.Thread(
296 name='MyServer serving',
297 target=s.serve_forever,
298 kwargs={'poll_interval':0.01})
299 t.daemon = True # In case this function raises.
300 threads.append((t, s))
301 for t, s in threads:
302 t.start()
303 s.shutdown()
304 for t, s in threads:
305 t.join()
306
Guido van Rossum39f1b362001-07-10 11:52:38 +0000307
Tim Petersa9f6f222001-09-17 23:56:20 +0000308def test_main():
Tim Petersa9f6f222001-09-17 23:56:20 +0000309 if imp.lock_held():
Georg Brandl61fdd712008-02-02 11:05:00 +0000310 # If the import lock is held, the threads will hang
Benjamin Petersonbec087f2009-03-26 21:10:30 +0000311 raise unittest.SkipTest("can't run when import lock is held")
Tim Petersa9f6f222001-09-17 23:56:20 +0000312
Georg Brandl61fdd712008-02-02 11:05:00 +0000313 test.test_support.run_unittest(SocketServerTest)
Guido van Rossum39f1b362001-07-10 11:52:38 +0000314
Tim Petersa9f6f222001-09-17 23:56:20 +0000315if __name__ == "__main__":
316 test_main()