blob: d4c3621b79001ddf50474caff32c7045f4e52ec8 [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 Heimes292d3512008-02-03 16:51:08 +00006import imp
Christian Heimes9e7f1d22008-02-28 12:27:11 +00007import os
Guido van Rossum39f1b362001-07-10 11:52:38 +00008import select
Christian Heimes9e7f1d22008-02-28 12:27:11 +00009import signal
10import socket
11import tempfile
Christian Heimes292d3512008-02-03 16:51:08 +000012import unittest
Alexandre Vassalottice261952008-05-12 02:31:37 +000013import socketserver
Christian Heimes292d3512008-02-03 16:51:08 +000014
Benjamin Petersonee8712c2008-05-20 21:35:26 +000015import test.support
Antoine Pitrouc00d4b42009-10-27 21:32:38 +000016from test.support import reap_children, reap_threads, verbose
Victor Stinner45df8202010-04-28 22:31:17 +000017try:
18 import threading
19except ImportError:
20 threading = None
Christian Heimes292d3512008-02-03 16:51:08 +000021
Benjamin Petersonee8712c2008-05-20 21:35:26 +000022test.support.requires("network")
Guido van Rossum39f1b362001-07-10 11:52:38 +000023
Christian Heimes292d3512008-02-03 16:51:08 +000024TEST_STR = b"hello world\n"
Benjamin Petersonee8712c2008-05-20 21:35:26 +000025HOST = test.support.HOST
Christian Heimes292d3512008-02-03 16:51:08 +000026
27HAVE_UNIX_SOCKETS = hasattr(socket, "AF_UNIX")
28HAVE_FORKING = hasattr(os, "fork") and os.name != "os2"
29
Christian Heimesdd15f6c2008-03-16 00:07:10 +000030def signal_alarm(n):
31 """Call signal.alarm when it exists (i.e. not on Windows)."""
32 if hasattr(signal, 'alarm'):
33 signal.alarm(n)
Guido van Rossum39f1b362001-07-10 11:52:38 +000034
Christian Heimes292d3512008-02-03 16:51:08 +000035def receive(sock, n, timeout=20):
36 r, w, x = select.select([sock], [], [], timeout)
37 if sock in r:
38 return sock.recv(n)
39 else:
40 raise RuntimeError("timed out on %r" % (sock,))
41
Christian Heimes15ebc882008-02-04 18:48:49 +000042if HAVE_UNIX_SOCKETS:
Alexandre Vassalottice261952008-05-12 02:31:37 +000043 class ForkingUnixStreamServer(socketserver.ForkingMixIn,
44 socketserver.UnixStreamServer):
Christian Heimes15ebc882008-02-04 18:48:49 +000045 pass
Christian Heimes292d3512008-02-03 16:51:08 +000046
Alexandre Vassalottice261952008-05-12 02:31:37 +000047 class ForkingUnixDatagramServer(socketserver.ForkingMixIn,
48 socketserver.UnixDatagramServer):
Christian Heimes15ebc882008-02-04 18:48:49 +000049 pass
Christian Heimes292d3512008-02-03 16:51:08 +000050
51
Christian Heimes70e7ea22008-02-28 20:02:27 +000052@contextlib.contextmanager
53def simple_subprocess(testcase):
54 pid = os.fork()
55 if pid == 0:
56 # Don't throw an exception; it would be caught by the test harness.
57 os._exit(72)
58 yield None
59 pid2, status = os.waitpid(pid, 0)
Ezio Melottib3aedd42010-11-20 19:04:17 +000060 testcase.assertEqual(pid2, pid)
61 testcase.assertEqual(72 << 8, status)
Christian Heimes70e7ea22008-02-28 20:02:27 +000062
63
Victor Stinner5f22e722010-05-26 17:33:03 +000064@unittest.skipUnless(threading, 'Threading required for this test.')
Christian Heimes292d3512008-02-03 16:51:08 +000065class SocketServerTest(unittest.TestCase):
66 """Test all socket servers."""
Guido van Rossum39f1b362001-07-10 11:52:38 +000067
Christian Heimes292d3512008-02-03 16:51:08 +000068 def setUp(self):
Christian Heimesdd15f6c2008-03-16 00:07:10 +000069 signal_alarm(20) # Kill deadlocks after 20 seconds.
Christian Heimes292d3512008-02-03 16:51:08 +000070 self.port_seed = 0
71 self.test_files = []
Guido van Rossum39f1b362001-07-10 11:52:38 +000072
Christian Heimes292d3512008-02-03 16:51:08 +000073 def tearDown(self):
Christian Heimesfe337bf2008-03-23 21:54:12 +000074 signal_alarm(0) # Didn't deadlock.
Christian Heimes292d3512008-02-03 16:51:08 +000075 reap_children()
Thomas Wouters00ee7ba2006-08-21 19:07:27 +000076
Christian Heimes292d3512008-02-03 16:51:08 +000077 for fn in self.test_files:
78 try:
79 os.remove(fn)
80 except os.error:
81 pass
82 self.test_files[:] = []
Christian Heimes292d3512008-02-03 16:51:08 +000083
84 def pickaddr(self, proto):
85 if proto == socket.AF_INET:
Christian Heimes9e7f1d22008-02-28 12:27:11 +000086 return (HOST, 0)
Christian Heimes292d3512008-02-03 16:51:08 +000087 else:
Christian Heimes9e7f1d22008-02-28 12:27:11 +000088 # XXX: We need a way to tell AF_UNIX to pick its own name
89 # like AF_INET provides port==0.
90 dir = None
91 if os.name == 'os2':
92 dir = '\socket'
93 fn = tempfile.mktemp(prefix='unix_socket.', dir=dir)
Christian Heimes292d3512008-02-03 16:51:08 +000094 if os.name == 'os2':
95 # AF_UNIX socket names on OS/2 require a specific prefix
96 # which can't include a drive letter and must also use
97 # backslashes as directory separators
98 if fn[1] == ':':
99 fn = fn[2:]
100 if fn[0] in (os.sep, os.altsep):
101 fn = fn[1:]
Christian Heimes292d3512008-02-03 16:51:08 +0000102 if os.sep == '/':
103 fn = fn.replace(os.sep, os.altsep)
104 else:
105 fn = fn.replace(os.altsep, os.sep)
106 self.test_files.append(fn)
107 return fn
108
Christian Heimesdd15f6c2008-03-16 00:07:10 +0000109 def make_server(self, addr, svrcls, hdlrbase):
110 class MyServer(svrcls):
111 def handle_error(self, request, client_address):
112 self.close_request(request)
113 self.server_close()
114 raise
Christian Heimes9e7f1d22008-02-28 12:27:11 +0000115
Christian Heimes9e7f1d22008-02-28 12:27:11 +0000116 class MyHandler(hdlrbase):
117 def handle(self):
118 line = self.rfile.readline()
119 self.wfile.write(line)
120
Christian Heimesdd15f6c2008-03-16 00:07:10 +0000121 if verbose: print("creating server")
122 server = MyServer(addr, MyHandler)
Ezio Melottib3aedd42010-11-20 19:04:17 +0000123 self.assertEqual(server.server_address, server.socket.getsockname())
Christian Heimesdd15f6c2008-03-16 00:07:10 +0000124 return server
125
Victor Stinner45df8202010-04-28 22:31:17 +0000126 @unittest.skipUnless(threading, 'Threading required for this test.')
Antoine Pitrouc00d4b42009-10-27 21:32:38 +0000127 @reap_threads
Christian Heimesdd15f6c2008-03-16 00:07:10 +0000128 def run_server(self, svrcls, hdlrbase, testfunc):
129 server = self.make_server(self.pickaddr(svrcls.address_family),
130 svrcls, hdlrbase)
131 # We had the OS pick a port, so pull the real address out of
132 # the server.
133 addr = server.server_address
Christian Heimes9e7f1d22008-02-28 12:27:11 +0000134 if verbose:
135 print("ADDR =", addr)
136 print("CLASS =", svrcls)
Christian Heimesdd15f6c2008-03-16 00:07:10 +0000137
138 t = threading.Thread(
139 name='%s serving' % svrcls,
140 target=server.serve_forever,
141 # Short poll interval to make the test finish quickly.
142 # Time between requests is short enough that we won't wake
143 # up spuriously too many times.
144 kwargs={'poll_interval':0.01})
Benjamin Peterson72753702008-08-18 18:09:21 +0000145 t.daemon = True # In case this function raises.
Christian Heimes9e7f1d22008-02-28 12:27:11 +0000146 t.start()
147 if verbose: print("server running")
Christian Heimesdd15f6c2008-03-16 00:07:10 +0000148 for i in range(3):
Christian Heimes9e7f1d22008-02-28 12:27:11 +0000149 if verbose: print("test client", i)
150 testfunc(svrcls.address_family, addr)
151 if verbose: print("waiting for server")
Christian Heimesdd15f6c2008-03-16 00:07:10 +0000152 server.shutdown()
Christian Heimes9e7f1d22008-02-28 12:27:11 +0000153 t.join()
Victor Stinner109761b2011-01-03 14:30:39 +0000154 server.server_close()
Christian Heimes9e7f1d22008-02-28 12:27:11 +0000155 if verbose: print("done")
Christian Heimes292d3512008-02-03 16:51:08 +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)
Christian Heimesfdb6bb52008-02-03 17:32:13 +0000162 while data and b'\n' not in buf:
Christian Heimes292d3512008-02-03 16:51:08 +0000163 data = receive(s, 100)
164 buf += data
Ezio Melottib3aedd42010-11-20 19:04:17 +0000165 self.assertEqual(buf, TEST_STR)
Christian Heimes292d3512008-02-03 16:51:08 +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)
Christian Heimesfdb6bb52008-02-03 17:32:13 +0000172 while data and b'\n' not in buf:
Christian Heimes292d3512008-02-03 16:51:08 +0000173 data = receive(s, 100)
174 buf += data
Ezio Melottib3aedd42010-11-20 19:04:17 +0000175 self.assertEqual(buf, TEST_STR)
Christian Heimes292d3512008-02-03 16:51:08 +0000176 s.close()
177
Christian Heimes9e7f1d22008-02-28 12:27:11 +0000178 def test_TCPServer(self):
Alexandre Vassalottice261952008-05-12 02:31:37 +0000179 self.run_server(socketserver.TCPServer,
180 socketserver.StreamRequestHandler,
Christian Heimes9e7f1d22008-02-28 12:27:11 +0000181 self.stream_examine)
Christian Heimes292d3512008-02-03 16:51:08 +0000182
Christian Heimes9e7f1d22008-02-28 12:27:11 +0000183 def test_ThreadingTCPServer(self):
Alexandre Vassalottice261952008-05-12 02:31:37 +0000184 self.run_server(socketserver.ThreadingTCPServer,
185 socketserver.StreamRequestHandler,
Christian Heimes9e7f1d22008-02-28 12:27:11 +0000186 self.stream_examine)
Christian Heimes292d3512008-02-03 16:51:08 +0000187
Christian Heimes9e7f1d22008-02-28 12:27:11 +0000188 if HAVE_FORKING:
Christian Heimes70e7ea22008-02-28 20:02:27 +0000189 def test_ForkingTCPServer(self):
190 with simple_subprocess(self):
Alexandre Vassalottice261952008-05-12 02:31:37 +0000191 self.run_server(socketserver.ForkingTCPServer,
192 socketserver.StreamRequestHandler,
Christian Heimes70e7ea22008-02-28 20:02:27 +0000193 self.stream_examine)
Christian Heimes9e7f1d22008-02-28 12:27:11 +0000194
195 if HAVE_UNIX_SOCKETS:
196 def test_UnixStreamServer(self):
Alexandre Vassalottice261952008-05-12 02:31:37 +0000197 self.run_server(socketserver.UnixStreamServer,
198 socketserver.StreamRequestHandler,
Christian Heimes9e7f1d22008-02-28 12:27:11 +0000199 self.stream_examine)
200
201 def test_ThreadingUnixStreamServer(self):
Alexandre Vassalottice261952008-05-12 02:31:37 +0000202 self.run_server(socketserver.ThreadingUnixStreamServer,
203 socketserver.StreamRequestHandler,
Christian Heimes9e7f1d22008-02-28 12:27:11 +0000204 self.stream_examine)
205
Christian Heimes292d3512008-02-03 16:51:08 +0000206 if HAVE_FORKING:
Christian Heimes9e7f1d22008-02-28 12:27:11 +0000207 def test_ForkingUnixStreamServer(self):
Christian Heimes70e7ea22008-02-28 20:02:27 +0000208 with simple_subprocess(self):
209 self.run_server(ForkingUnixStreamServer,
Alexandre Vassalottice261952008-05-12 02:31:37 +0000210 socketserver.StreamRequestHandler,
Christian Heimes70e7ea22008-02-28 20:02:27 +0000211 self.stream_examine)
Christian Heimes9e7f1d22008-02-28 12:27:11 +0000212
213 def test_UDPServer(self):
Alexandre Vassalottice261952008-05-12 02:31:37 +0000214 self.run_server(socketserver.UDPServer,
215 socketserver.DatagramRequestHandler,
Christian Heimes9e7f1d22008-02-28 12:27:11 +0000216 self.dgram_examine)
217
218 def test_ThreadingUDPServer(self):
Alexandre Vassalottice261952008-05-12 02:31:37 +0000219 self.run_server(socketserver.ThreadingUDPServer,
220 socketserver.DatagramRequestHandler,
Christian Heimes9e7f1d22008-02-28 12:27:11 +0000221 self.dgram_examine)
222
223 if HAVE_FORKING:
224 def test_ForkingUDPServer(self):
Christian Heimes70e7ea22008-02-28 20:02:27 +0000225 with simple_subprocess(self):
Alexandre Vassalottice261952008-05-12 02:31:37 +0000226 self.run_server(socketserver.ForkingUDPServer,
227 socketserver.DatagramRequestHandler,
Christian Heimes70e7ea22008-02-28 20:02:27 +0000228 self.dgram_examine)
Christian Heimes292d3512008-02-03 16:51:08 +0000229
230 # Alas, on Linux (at least) recvfrom() doesn't return a meaningful
231 # client address so this cannot work:
232
Christian Heimes9e7f1d22008-02-28 12:27:11 +0000233 # if HAVE_UNIX_SOCKETS:
234 # def test_UnixDatagramServer(self):
Alexandre Vassalottice261952008-05-12 02:31:37 +0000235 # self.run_server(socketserver.UnixDatagramServer,
236 # socketserver.DatagramRequestHandler,
Christian Heimes9e7f1d22008-02-28 12:27:11 +0000237 # self.dgram_examine)
238 #
239 # def test_ThreadingUnixDatagramServer(self):
Alexandre Vassalottice261952008-05-12 02:31:37 +0000240 # self.run_server(socketserver.ThreadingUnixDatagramServer,
241 # socketserver.DatagramRequestHandler,
Christian Heimes9e7f1d22008-02-28 12:27:11 +0000242 # self.dgram_examine)
243 #
Christian Heimes292d3512008-02-03 16:51:08 +0000244 # if HAVE_FORKING:
Christian Heimes9e7f1d22008-02-28 12:27:11 +0000245 # def test_ForkingUnixDatagramServer(self):
Alexandre Vassalottice261952008-05-12 02:31:37 +0000246 # self.run_server(socketserver.ForkingUnixDatagramServer,
247 # socketserver.DatagramRequestHandler,
Christian Heimes9e7f1d22008-02-28 12:27:11 +0000248 # self.dgram_examine)
Christian Heimes292d3512008-02-03 16:51:08 +0000249
Antoine Pitrou3bcba8e2010-04-25 22:01:43 +0000250 @reap_threads
251 def test_shutdown(self):
252 # Issue #2302: shutdown() should always succeed in making an
253 # other thread leave serve_forever().
254 class MyServer(socketserver.TCPServer):
255 pass
256
257 class MyHandler(socketserver.StreamRequestHandler):
258 pass
259
260 threads = []
261 for i in range(20):
262 s = MyServer((HOST, 0), MyHandler)
263 t = threading.Thread(
264 name='MyServer serving',
265 target=s.serve_forever,
266 kwargs={'poll_interval':0.01})
267 t.daemon = True # In case this function raises.
268 threads.append((t, s))
269 for t, s in threads:
270 t.start()
271 s.shutdown()
272 for t, s in threads:
273 t.join()
Victor Stinner109761b2011-01-03 14:30:39 +0000274 s.server_close()
Antoine Pitrou3bcba8e2010-04-25 22:01:43 +0000275
Guido van Rossum39f1b362001-07-10 11:52:38 +0000276
Tim Petersa9f6f222001-09-17 23:56:20 +0000277def test_main():
Tim Petersa9f6f222001-09-17 23:56:20 +0000278 if imp.lock_held():
Christian Heimes292d3512008-02-03 16:51:08 +0000279 # If the import lock is held, the threads will hang
Benjamin Petersone549ead2009-03-28 21:42:05 +0000280 raise unittest.SkipTest("can't run when import lock is held")
Tim Petersa9f6f222001-09-17 23:56:20 +0000281
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000282 test.support.run_unittest(SocketServerTest)
Guido van Rossum39f1b362001-07-10 11:52:38 +0000283
Tim Petersa9f6f222001-09-17 23:56:20 +0000284if __name__ == "__main__":
285 test_main()
Christian Heimesdd15f6c2008-03-16 00:07:10 +0000286 signal_alarm(3) # Shutdown shouldn't take more than 3 seconds.