blob: 0dbb8e2ed0d72b1c1f3b6ed6c333d49feee578cc [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
Antoine Pitrou467a5c42012-04-09 01:15:06 +020037# Remember real select() to avoid interferences with mocking
38_real_select = select.select
39
Guido van Rossum39f1b362001-07-10 11:52:38 +000040def receive(sock, n, timeout=20):
Antoine Pitrou467a5c42012-04-09 01:15:06 +020041 r, w, x = _real_select([sock], [], [], timeout)
Guido van Rossum39f1b362001-07-10 11:52:38 +000042 if sock in r:
43 return sock.recv(n)
44 else:
Walter Dörwald70a6b492004-02-12 17:35:32 +000045 raise RuntimeError, "timed out on %r" % (sock,)
Guido van Rossum39f1b362001-07-10 11:52:38 +000046
Amaury Forgeot d'Arc72a65762008-02-03 23:57:24 +000047if HAVE_UNIX_SOCKETS:
Georg Brandle152a772008-05-24 18:31:28 +000048 class ForkingUnixStreamServer(SocketServer.ForkingMixIn,
49 SocketServer.UnixStreamServer):
Amaury Forgeot d'Arc72a65762008-02-03 23:57:24 +000050 pass
Georg Brandl61fdd712008-02-02 11:05:00 +000051
Georg Brandle152a772008-05-24 18:31:28 +000052 class ForkingUnixDatagramServer(SocketServer.ForkingMixIn,
53 SocketServer.UnixDatagramServer):
Amaury Forgeot d'Arc72a65762008-02-03 23:57:24 +000054 pass
Georg Brandl61fdd712008-02-02 11:05:00 +000055
56
Jeffrey Yasskin392c1592008-02-28 18:03:15 +000057@contextlib.contextmanager
58def simple_subprocess(testcase):
59 pid = os.fork()
60 if pid == 0:
Andrew Svetlov4bb142b2012-12-18 21:27:37 +020061 # Don't raise an exception; it would be caught by the test harness.
Jeffrey Yasskin392c1592008-02-28 18:03:15 +000062 os._exit(72)
63 yield None
64 pid2, status = os.waitpid(pid, 0)
Ezio Melotti2623a372010-11-21 13:34:58 +000065 testcase.assertEqual(pid2, pid)
66 testcase.assertEqual(72 << 8, status)
Jeffrey Yasskin392c1592008-02-28 18:03:15 +000067
68
Victor Stinner708c0722010-05-26 17:25:28 +000069@unittest.skipUnless(threading, 'Threading required for this test.')
Georg Brandl61fdd712008-02-02 11:05:00 +000070class SocketServerTest(unittest.TestCase):
71 """Test all socket servers."""
Guido van Rossum39f1b362001-07-10 11:52:38 +000072
Georg Brandl61fdd712008-02-02 11:05:00 +000073 def setUp(self):
Victor Stinnerb30ac942011-07-14 14:53:24 +020074 signal_alarm(60) # Kill deadlocks after 60 seconds.
Georg Brandl61fdd712008-02-02 11:05:00 +000075 self.port_seed = 0
76 self.test_files = []
Neal Norwitzb476fdf2006-08-15 04:58:28 +000077
Georg Brandl61fdd712008-02-02 11:05:00 +000078 def tearDown(self):
Neal Norwitzacdb6fb2008-03-23 06:16:04 +000079 signal_alarm(0) # Didn't deadlock.
Georg Brandl61fdd712008-02-02 11:05:00 +000080 reap_children()
81
82 for fn in self.test_files:
83 try:
84 os.remove(fn)
85 except os.error:
86 pass
87 self.test_files[:] = []
Georg Brandl61fdd712008-02-02 11:05:00 +000088
89 def pickaddr(self, proto):
90 if proto == socket.AF_INET:
Jeffrey Yasskin180997b2008-02-28 05:53:18 +000091 return (HOST, 0)
Georg Brandl61fdd712008-02-02 11:05:00 +000092 else:
Jeffrey Yasskin180997b2008-02-28 05:53:18 +000093 # XXX: We need a way to tell AF_UNIX to pick its own name
94 # like AF_INET provides port==0.
95 dir = None
96 if os.name == 'os2':
97 dir = '\socket'
98 fn = tempfile.mktemp(prefix='unix_socket.', dir=dir)
Georg Brandl61fdd712008-02-02 11:05:00 +000099 if os.name == 'os2':
100 # AF_UNIX socket names on OS/2 require a specific prefix
101 # which can't include a drive letter and must also use
102 # backslashes as directory separators
103 if fn[1] == ':':
104 fn = fn[2:]
105 if fn[0] in (os.sep, os.altsep):
106 fn = fn[1:]
Georg Brandl61fdd712008-02-02 11:05:00 +0000107 if os.sep == '/':
108 fn = fn.replace(os.sep, os.altsep)
109 else:
110 fn = fn.replace(os.altsep, os.sep)
111 self.test_files.append(fn)
112 return fn
113
Jeffrey Yasskine75f59a2008-03-07 06:22:15 +0000114 def make_server(self, addr, svrcls, hdlrbase):
115 class MyServer(svrcls):
116 def handle_error(self, request, client_address):
117 self.close_request(request)
118 self.server_close()
119 raise
120
Jeffrey Yasskin180997b2008-02-28 05:53:18 +0000121 class MyHandler(hdlrbase):
122 def handle(self):
123 line = self.rfile.readline()
124 self.wfile.write(line)
125
Jeffrey Yasskine75f59a2008-03-07 06:22:15 +0000126 if verbose: print "creating server"
127 server = MyServer(addr, MyHandler)
Ezio Melotti2623a372010-11-21 13:34:58 +0000128 self.assertEqual(server.server_address, server.socket.getsockname())
Jeffrey Yasskine75f59a2008-03-07 06:22:15 +0000129 return server
130
Antoine Pitrou8aea0502009-10-27 21:27:24 +0000131 @reap_threads
Jeffrey Yasskine75f59a2008-03-07 06:22:15 +0000132 def run_server(self, svrcls, hdlrbase, testfunc):
133 server = self.make_server(self.pickaddr(svrcls.address_family),
134 svrcls, hdlrbase)
135 # We had the OS pick a port, so pull the real address out of
136 # the server.
137 addr = server.server_address
Jeffrey Yasskin180997b2008-02-28 05:53:18 +0000138 if verbose:
Jeffrey Yasskine75f59a2008-03-07 06:22:15 +0000139 print "server created"
Jeffrey Yasskin180997b2008-02-28 05:53:18 +0000140 print "ADDR =", addr
141 print "CLASS =", svrcls
Jeffrey Yasskine75f59a2008-03-07 06:22:15 +0000142 t = threading.Thread(
143 name='%s serving' % svrcls,
144 target=server.serve_forever,
145 # Short poll interval to make the test finish quickly.
146 # Time between requests is short enough that we won't wake
147 # up spuriously too many times.
148 kwargs={'poll_interval':0.01})
Benjamin Petersona9b22222008-08-18 18:01:43 +0000149 t.daemon = True # In case this function raises.
Jeffrey Yasskin180997b2008-02-28 05:53:18 +0000150 t.start()
151 if verbose: print "server running"
Jeffrey Yasskine75f59a2008-03-07 06:22:15 +0000152 for i in range(3):
Jeffrey Yasskin180997b2008-02-28 05:53:18 +0000153 if verbose: print "test client", i
154 testfunc(svrcls.address_family, addr)
155 if verbose: print "waiting for server"
Jeffrey Yasskine75f59a2008-03-07 06:22:15 +0000156 server.shutdown()
Jeffrey Yasskin180997b2008-02-28 05:53:18 +0000157 t.join()
158 if verbose: print "done"
Georg Brandl61fdd712008-02-02 11:05:00 +0000159
160 def stream_examine(self, proto, addr):
161 s = socket.socket(proto, socket.SOCK_STREAM)
162 s.connect(addr)
163 s.sendall(TEST_STR)
164 buf = data = receive(s, 100)
165 while data and '\n' not in buf:
166 data = receive(s, 100)
167 buf += data
Ezio Melotti2623a372010-11-21 13:34:58 +0000168 self.assertEqual(buf, TEST_STR)
Georg Brandl61fdd712008-02-02 11:05:00 +0000169 s.close()
170
171 def dgram_examine(self, proto, addr):
172 s = socket.socket(proto, socket.SOCK_DGRAM)
173 s.sendto(TEST_STR, addr)
174 buf = data = receive(s, 100)
175 while data and '\n' not in buf:
176 data = receive(s, 100)
177 buf += data
Ezio Melotti2623a372010-11-21 13:34:58 +0000178 self.assertEqual(buf, TEST_STR)
Georg Brandl61fdd712008-02-02 11:05:00 +0000179 s.close()
180
Jeffrey Yasskin180997b2008-02-28 05:53:18 +0000181 def test_TCPServer(self):
Georg Brandle152a772008-05-24 18:31:28 +0000182 self.run_server(SocketServer.TCPServer,
183 SocketServer.StreamRequestHandler,
Jeffrey Yasskin180997b2008-02-28 05:53:18 +0000184 self.stream_examine)
Georg Brandl61fdd712008-02-02 11:05:00 +0000185
Jeffrey Yasskin180997b2008-02-28 05:53:18 +0000186 def test_ThreadingTCPServer(self):
Georg Brandle152a772008-05-24 18:31:28 +0000187 self.run_server(SocketServer.ThreadingTCPServer,
188 SocketServer.StreamRequestHandler,
Jeffrey Yasskin180997b2008-02-28 05:53:18 +0000189 self.stream_examine)
Georg Brandl61fdd712008-02-02 11:05:00 +0000190
Jeffrey Yasskin180997b2008-02-28 05:53:18 +0000191 if HAVE_FORKING:
Jeffrey Yasskin392c1592008-02-28 18:03:15 +0000192 def test_ForkingTCPServer(self):
193 with simple_subprocess(self):
Georg Brandle152a772008-05-24 18:31:28 +0000194 self.run_server(SocketServer.ForkingTCPServer,
195 SocketServer.StreamRequestHandler,
Jeffrey Yasskin392c1592008-02-28 18:03:15 +0000196 self.stream_examine)
Jeffrey Yasskin180997b2008-02-28 05:53:18 +0000197
198 if HAVE_UNIX_SOCKETS:
199 def test_UnixStreamServer(self):
Georg Brandle152a772008-05-24 18:31:28 +0000200 self.run_server(SocketServer.UnixStreamServer,
201 SocketServer.StreamRequestHandler,
Jeffrey Yasskin180997b2008-02-28 05:53:18 +0000202 self.stream_examine)
203
204 def test_ThreadingUnixStreamServer(self):
Georg Brandle152a772008-05-24 18:31:28 +0000205 self.run_server(SocketServer.ThreadingUnixStreamServer,
206 SocketServer.StreamRequestHandler,
Jeffrey Yasskin180997b2008-02-28 05:53:18 +0000207 self.stream_examine)
208
Georg Brandl61fdd712008-02-02 11:05:00 +0000209 if HAVE_FORKING:
Jeffrey Yasskin180997b2008-02-28 05:53:18 +0000210 def test_ForkingUnixStreamServer(self):
Jeffrey Yasskin392c1592008-02-28 18:03:15 +0000211 with simple_subprocess(self):
212 self.run_server(ForkingUnixStreamServer,
Georg Brandle152a772008-05-24 18:31:28 +0000213 SocketServer.StreamRequestHandler,
Jeffrey Yasskin392c1592008-02-28 18:03:15 +0000214 self.stream_examine)
Jeffrey Yasskin180997b2008-02-28 05:53:18 +0000215
216 def test_UDPServer(self):
Georg Brandle152a772008-05-24 18:31:28 +0000217 self.run_server(SocketServer.UDPServer,
218 SocketServer.DatagramRequestHandler,
Jeffrey Yasskin180997b2008-02-28 05:53:18 +0000219 self.dgram_examine)
220
221 def test_ThreadingUDPServer(self):
Georg Brandle152a772008-05-24 18:31:28 +0000222 self.run_server(SocketServer.ThreadingUDPServer,
223 SocketServer.DatagramRequestHandler,
Jeffrey Yasskin180997b2008-02-28 05:53:18 +0000224 self.dgram_examine)
225
226 if HAVE_FORKING:
227 def test_ForkingUDPServer(self):
Jeffrey Yasskin392c1592008-02-28 18:03:15 +0000228 with simple_subprocess(self):
Georg Brandle152a772008-05-24 18:31:28 +0000229 self.run_server(SocketServer.ForkingUDPServer,
230 SocketServer.DatagramRequestHandler,
Jeffrey Yasskin392c1592008-02-28 18:03:15 +0000231 self.dgram_examine)
Georg Brandl61fdd712008-02-02 11:05:00 +0000232
Antoine Pitroufa1d8412012-04-09 00:47:24 +0200233 @contextlib.contextmanager
234 def mocked_select_module(self):
235 """Mocks the select.select() call to raise EINTR for first call"""
236 old_select = select.select
237
238 class MockSelect:
239 def __init__(self):
240 self.called = 0
241
242 def __call__(self, *args):
243 self.called += 1
244 if self.called == 1:
245 # raise the exception on first call
Antoine Pitroub5588c32012-04-09 01:41:34 +0200246 raise select.error(errno.EINTR, os.strerror(errno.EINTR))
Antoine Pitroufa1d8412012-04-09 00:47:24 +0200247 else:
248 # Return real select value for consecutive calls
249 return old_select(*args)
250
251 select.select = MockSelect()
252 try:
253 yield select.select
254 finally:
255 select.select = old_select
256
257 def test_InterruptServerSelectCall(self):
258 with self.mocked_select_module() as mock_select:
259 pid = self.run_server(SocketServer.TCPServer,
260 SocketServer.StreamRequestHandler,
261 self.stream_examine)
262 # Make sure select was called again:
263 self.assertGreater(mock_select.called, 1)
264
Georg Brandl61fdd712008-02-02 11:05:00 +0000265 # Alas, on Linux (at least) recvfrom() doesn't return a meaningful
266 # client address so this cannot work:
267
Jeffrey Yasskin180997b2008-02-28 05:53:18 +0000268 # if HAVE_UNIX_SOCKETS:
269 # def test_UnixDatagramServer(self):
Georg Brandle152a772008-05-24 18:31:28 +0000270 # self.run_server(SocketServer.UnixDatagramServer,
271 # SocketServer.DatagramRequestHandler,
Jeffrey Yasskin180997b2008-02-28 05:53:18 +0000272 # self.dgram_examine)
273 #
274 # def test_ThreadingUnixDatagramServer(self):
Georg Brandle152a772008-05-24 18:31:28 +0000275 # self.run_server(SocketServer.ThreadingUnixDatagramServer,
276 # SocketServer.DatagramRequestHandler,
Jeffrey Yasskin180997b2008-02-28 05:53:18 +0000277 # self.dgram_examine)
278 #
Georg Brandl61fdd712008-02-02 11:05:00 +0000279 # if HAVE_FORKING:
Jeffrey Yasskin180997b2008-02-28 05:53:18 +0000280 # def test_ForkingUnixDatagramServer(self):
Georg Brandle152a772008-05-24 18:31:28 +0000281 # self.run_server(SocketServer.ForkingUnixDatagramServer,
282 # SocketServer.DatagramRequestHandler,
Jeffrey Yasskin180997b2008-02-28 05:53:18 +0000283 # self.dgram_examine)
Georg Brandl61fdd712008-02-02 11:05:00 +0000284
Antoine Pitroua6240402010-04-25 21:40:32 +0000285 @reap_threads
286 def test_shutdown(self):
287 # Issue #2302: shutdown() should always succeed in making an
288 # other thread leave serve_forever().
289 class MyServer(SocketServer.TCPServer):
290 pass
291
292 class MyHandler(SocketServer.StreamRequestHandler):
293 pass
294
295 threads = []
296 for i in range(20):
297 s = MyServer((HOST, 0), MyHandler)
298 t = threading.Thread(
299 name='MyServer serving',
300 target=s.serve_forever,
301 kwargs={'poll_interval':0.01})
302 t.daemon = True # In case this function raises.
303 threads.append((t, s))
304 for t, s in threads:
305 t.start()
306 s.shutdown()
307 for t, s in threads:
308 t.join()
309
Guido van Rossum39f1b362001-07-10 11:52:38 +0000310
Tim Petersa9f6f222001-09-17 23:56:20 +0000311def test_main():
Tim Petersa9f6f222001-09-17 23:56:20 +0000312 if imp.lock_held():
Georg Brandl61fdd712008-02-02 11:05:00 +0000313 # If the import lock is held, the threads will hang
Benjamin Petersonbec087f2009-03-26 21:10:30 +0000314 raise unittest.SkipTest("can't run when import lock is held")
Tim Petersa9f6f222001-09-17 23:56:20 +0000315
Georg Brandl61fdd712008-02-02 11:05:00 +0000316 test.test_support.run_unittest(SocketServerTest)
Guido van Rossum39f1b362001-07-10 11:52:38 +0000317
Tim Petersa9f6f222001-09-17 23:56:20 +0000318if __name__ == "__main__":
319 test_main()