blob: 08fb03350d6c1fad3b0a98601cad7cf2c9ebab87 [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
11import tempfile
Georg Brandl61fdd712008-02-02 11:05:00 +000012import unittest
Georg Brandle152a772008-05-24 18:31:28 +000013import SocketServer
Georg Brandl61fdd712008-02-02 11:05:00 +000014
15import test.test_support
Antoine Pitrou8aea0502009-10-27 21:27:24 +000016from test.test_support import reap_children, reap_threads, verbose
Victor Stinner6a102812010-04-27 23:55:59 +000017try:
18 import threading
19except ImportError:
20 threading = None
Georg Brandl61fdd712008-02-02 11:05:00 +000021
22test.test_support.requires("network")
Guido van Rossum39f1b362001-07-10 11:52:38 +000023
Georg Brandl61fdd712008-02-02 11:05:00 +000024TEST_STR = "hello world\n"
Trent Nelsone41b0062008-04-08 23:47:30 +000025HOST = test.test_support.HOST
Georg Brandl61fdd712008-02-02 11:05:00 +000026
27HAVE_UNIX_SOCKETS = hasattr(socket, "AF_UNIX")
28HAVE_FORKING = hasattr(os, "fork") and os.name != "os2"
29
Jeffrey Yasskinf28896d2008-03-05 06:19:56 +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
Guido van Rossum39f1b362001-07-10 11:52:38 +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:
Walter Dörwald70a6b492004-02-12 17:35:32 +000040 raise RuntimeError, "timed out on %r" % (sock,)
Guido van Rossum39f1b362001-07-10 11:52:38 +000041
Amaury Forgeot d'Arc72a65762008-02-03 23:57:24 +000042if HAVE_UNIX_SOCKETS:
Georg Brandle152a772008-05-24 18:31:28 +000043 class ForkingUnixStreamServer(SocketServer.ForkingMixIn,
44 SocketServer.UnixStreamServer):
Amaury Forgeot d'Arc72a65762008-02-03 23:57:24 +000045 pass
Georg Brandl61fdd712008-02-02 11:05:00 +000046
Georg Brandle152a772008-05-24 18:31:28 +000047 class ForkingUnixDatagramServer(SocketServer.ForkingMixIn,
48 SocketServer.UnixDatagramServer):
Amaury Forgeot d'Arc72a65762008-02-03 23:57:24 +000049 pass
Georg Brandl61fdd712008-02-02 11:05:00 +000050
51
Jeffrey Yasskin392c1592008-02-28 18:03:15 +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 Melotti2623a372010-11-21 13:34:58 +000060 testcase.assertEqual(pid2, pid)
61 testcase.assertEqual(72 << 8, status)
Jeffrey Yasskin392c1592008-02-28 18:03:15 +000062
63
Victor Stinner708c0722010-05-26 17:25:28 +000064@unittest.skipUnless(threading, 'Threading required for this test.')
Georg Brandl61fdd712008-02-02 11:05:00 +000065class SocketServerTest(unittest.TestCase):
66 """Test all socket servers."""
Guido van Rossum39f1b362001-07-10 11:52:38 +000067
Georg Brandl61fdd712008-02-02 11:05:00 +000068 def setUp(self):
Victor Stinnerb30ac942011-07-14 14:53:24 +020069 signal_alarm(60) # Kill deadlocks after 60 seconds.
Georg Brandl61fdd712008-02-02 11:05:00 +000070 self.port_seed = 0
71 self.test_files = []
Neal Norwitzb476fdf2006-08-15 04:58:28 +000072
Georg Brandl61fdd712008-02-02 11:05:00 +000073 def tearDown(self):
Neal Norwitzacdb6fb2008-03-23 06:16:04 +000074 signal_alarm(0) # Didn't deadlock.
Georg Brandl61fdd712008-02-02 11:05:00 +000075 reap_children()
76
77 for fn in self.test_files:
78 try:
79 os.remove(fn)
80 except os.error:
81 pass
82 self.test_files[:] = []
Georg Brandl61fdd712008-02-02 11:05:00 +000083
84 def pickaddr(self, proto):
85 if proto == socket.AF_INET:
Jeffrey Yasskin180997b2008-02-28 05:53:18 +000086 return (HOST, 0)
Georg Brandl61fdd712008-02-02 11:05:00 +000087 else:
Jeffrey Yasskin180997b2008-02-28 05:53:18 +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)
Georg Brandl61fdd712008-02-02 11:05:00 +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:]
Georg Brandl61fdd712008-02-02 11:05:00 +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
Jeffrey Yasskine75f59a2008-03-07 06:22:15 +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
115
Jeffrey Yasskin180997b2008-02-28 05:53:18 +0000116 class MyHandler(hdlrbase):
117 def handle(self):
118 line = self.rfile.readline()
119 self.wfile.write(line)
120
Jeffrey Yasskine75f59a2008-03-07 06:22:15 +0000121 if verbose: print "creating server"
122 server = MyServer(addr, MyHandler)
Ezio Melotti2623a372010-11-21 13:34:58 +0000123 self.assertEqual(server.server_address, server.socket.getsockname())
Jeffrey Yasskine75f59a2008-03-07 06:22:15 +0000124 return server
125
Antoine Pitrou8aea0502009-10-27 21:27:24 +0000126 @reap_threads
Jeffrey Yasskine75f59a2008-03-07 06:22:15 +0000127 def run_server(self, svrcls, hdlrbase, testfunc):
128 server = self.make_server(self.pickaddr(svrcls.address_family),
129 svrcls, hdlrbase)
130 # We had the OS pick a port, so pull the real address out of
131 # the server.
132 addr = server.server_address
Jeffrey Yasskin180997b2008-02-28 05:53:18 +0000133 if verbose:
Jeffrey Yasskine75f59a2008-03-07 06:22:15 +0000134 print "server created"
Jeffrey Yasskin180997b2008-02-28 05:53:18 +0000135 print "ADDR =", addr
136 print "CLASS =", svrcls
Jeffrey Yasskine75f59a2008-03-07 06:22:15 +0000137 t = threading.Thread(
138 name='%s serving' % svrcls,
139 target=server.serve_forever,
140 # Short poll interval to make the test finish quickly.
141 # Time between requests is short enough that we won't wake
142 # up spuriously too many times.
143 kwargs={'poll_interval':0.01})
Benjamin Petersona9b22222008-08-18 18:01:43 +0000144 t.daemon = True # In case this function raises.
Jeffrey Yasskin180997b2008-02-28 05:53:18 +0000145 t.start()
146 if verbose: print "server running"
Jeffrey Yasskine75f59a2008-03-07 06:22:15 +0000147 for i in range(3):
Jeffrey Yasskin180997b2008-02-28 05:53:18 +0000148 if verbose: print "test client", i
149 testfunc(svrcls.address_family, addr)
150 if verbose: print "waiting for server"
Jeffrey Yasskine75f59a2008-03-07 06:22:15 +0000151 server.shutdown()
Jeffrey Yasskin180997b2008-02-28 05:53:18 +0000152 t.join()
153 if verbose: print "done"
Georg Brandl61fdd712008-02-02 11:05:00 +0000154
155 def stream_examine(self, proto, addr):
156 s = socket.socket(proto, socket.SOCK_STREAM)
157 s.connect(addr)
158 s.sendall(TEST_STR)
159 buf = data = receive(s, 100)
160 while data and '\n' not in buf:
161 data = receive(s, 100)
162 buf += data
Ezio Melotti2623a372010-11-21 13:34:58 +0000163 self.assertEqual(buf, TEST_STR)
Georg Brandl61fdd712008-02-02 11:05:00 +0000164 s.close()
165
166 def dgram_examine(self, proto, addr):
167 s = socket.socket(proto, socket.SOCK_DGRAM)
168 s.sendto(TEST_STR, addr)
169 buf = data = receive(s, 100)
170 while data and '\n' not in buf:
171 data = receive(s, 100)
172 buf += data
Ezio Melotti2623a372010-11-21 13:34:58 +0000173 self.assertEqual(buf, TEST_STR)
Georg Brandl61fdd712008-02-02 11:05:00 +0000174 s.close()
175
Jeffrey Yasskin180997b2008-02-28 05:53:18 +0000176 def test_TCPServer(self):
Georg Brandle152a772008-05-24 18:31:28 +0000177 self.run_server(SocketServer.TCPServer,
178 SocketServer.StreamRequestHandler,
Jeffrey Yasskin180997b2008-02-28 05:53:18 +0000179 self.stream_examine)
Georg Brandl61fdd712008-02-02 11:05:00 +0000180
Jeffrey Yasskin180997b2008-02-28 05:53:18 +0000181 def test_ThreadingTCPServer(self):
Georg Brandle152a772008-05-24 18:31:28 +0000182 self.run_server(SocketServer.ThreadingTCPServer,
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 if HAVE_FORKING:
Jeffrey Yasskin392c1592008-02-28 18:03:15 +0000187 def test_ForkingTCPServer(self):
188 with simple_subprocess(self):
Georg Brandle152a772008-05-24 18:31:28 +0000189 self.run_server(SocketServer.ForkingTCPServer,
190 SocketServer.StreamRequestHandler,
Jeffrey Yasskin392c1592008-02-28 18:03:15 +0000191 self.stream_examine)
Jeffrey Yasskin180997b2008-02-28 05:53:18 +0000192
193 if HAVE_UNIX_SOCKETS:
194 def test_UnixStreamServer(self):
Georg Brandle152a772008-05-24 18:31:28 +0000195 self.run_server(SocketServer.UnixStreamServer,
196 SocketServer.StreamRequestHandler,
Jeffrey Yasskin180997b2008-02-28 05:53:18 +0000197 self.stream_examine)
198
199 def test_ThreadingUnixStreamServer(self):
Georg Brandle152a772008-05-24 18:31:28 +0000200 self.run_server(SocketServer.ThreadingUnixStreamServer,
201 SocketServer.StreamRequestHandler,
Jeffrey Yasskin180997b2008-02-28 05:53:18 +0000202 self.stream_examine)
203
Georg Brandl61fdd712008-02-02 11:05:00 +0000204 if HAVE_FORKING:
Jeffrey Yasskin180997b2008-02-28 05:53:18 +0000205 def test_ForkingUnixStreamServer(self):
Jeffrey Yasskin392c1592008-02-28 18:03:15 +0000206 with simple_subprocess(self):
207 self.run_server(ForkingUnixStreamServer,
Georg Brandle152a772008-05-24 18:31:28 +0000208 SocketServer.StreamRequestHandler,
Jeffrey Yasskin392c1592008-02-28 18:03:15 +0000209 self.stream_examine)
Jeffrey Yasskin180997b2008-02-28 05:53:18 +0000210
211 def test_UDPServer(self):
Georg Brandle152a772008-05-24 18:31:28 +0000212 self.run_server(SocketServer.UDPServer,
213 SocketServer.DatagramRequestHandler,
Jeffrey Yasskin180997b2008-02-28 05:53:18 +0000214 self.dgram_examine)
215
216 def test_ThreadingUDPServer(self):
Georg Brandle152a772008-05-24 18:31:28 +0000217 self.run_server(SocketServer.ThreadingUDPServer,
218 SocketServer.DatagramRequestHandler,
Jeffrey Yasskin180997b2008-02-28 05:53:18 +0000219 self.dgram_examine)
220
221 if HAVE_FORKING:
222 def test_ForkingUDPServer(self):
Jeffrey Yasskin392c1592008-02-28 18:03:15 +0000223 with simple_subprocess(self):
Georg Brandle152a772008-05-24 18:31:28 +0000224 self.run_server(SocketServer.ForkingUDPServer,
225 SocketServer.DatagramRequestHandler,
Jeffrey Yasskin392c1592008-02-28 18:03:15 +0000226 self.dgram_examine)
Georg Brandl61fdd712008-02-02 11:05:00 +0000227
228 # Alas, on Linux (at least) recvfrom() doesn't return a meaningful
229 # client address so this cannot work:
230
Jeffrey Yasskin180997b2008-02-28 05:53:18 +0000231 # if HAVE_UNIX_SOCKETS:
232 # def test_UnixDatagramServer(self):
Georg Brandle152a772008-05-24 18:31:28 +0000233 # self.run_server(SocketServer.UnixDatagramServer,
234 # SocketServer.DatagramRequestHandler,
Jeffrey Yasskin180997b2008-02-28 05:53:18 +0000235 # self.dgram_examine)
236 #
237 # def test_ThreadingUnixDatagramServer(self):
Georg Brandle152a772008-05-24 18:31:28 +0000238 # self.run_server(SocketServer.ThreadingUnixDatagramServer,
239 # SocketServer.DatagramRequestHandler,
Jeffrey Yasskin180997b2008-02-28 05:53:18 +0000240 # self.dgram_examine)
241 #
Georg Brandl61fdd712008-02-02 11:05:00 +0000242 # if HAVE_FORKING:
Jeffrey Yasskin180997b2008-02-28 05:53:18 +0000243 # def test_ForkingUnixDatagramServer(self):
Georg Brandle152a772008-05-24 18:31:28 +0000244 # self.run_server(SocketServer.ForkingUnixDatagramServer,
245 # SocketServer.DatagramRequestHandler,
Jeffrey Yasskin180997b2008-02-28 05:53:18 +0000246 # self.dgram_examine)
Georg Brandl61fdd712008-02-02 11:05:00 +0000247
Antoine Pitroua6240402010-04-25 21:40:32 +0000248 @reap_threads
249 def test_shutdown(self):
250 # Issue #2302: shutdown() should always succeed in making an
251 # other thread leave serve_forever().
252 class MyServer(SocketServer.TCPServer):
253 pass
254
255 class MyHandler(SocketServer.StreamRequestHandler):
256 pass
257
258 threads = []
259 for i in range(20):
260 s = MyServer((HOST, 0), MyHandler)
261 t = threading.Thread(
262 name='MyServer serving',
263 target=s.serve_forever,
264 kwargs={'poll_interval':0.01})
265 t.daemon = True # In case this function raises.
266 threads.append((t, s))
267 for t, s in threads:
268 t.start()
269 s.shutdown()
270 for t, s in threads:
271 t.join()
272
Guido van Rossum39f1b362001-07-10 11:52:38 +0000273
Tim Petersa9f6f222001-09-17 23:56:20 +0000274def test_main():
Tim Petersa9f6f222001-09-17 23:56:20 +0000275 if imp.lock_held():
Georg Brandl61fdd712008-02-02 11:05:00 +0000276 # If the import lock is held, the threads will hang
Benjamin Petersonbec087f2009-03-26 21:10:30 +0000277 raise unittest.SkipTest("can't run when import lock is held")
Tim Petersa9f6f222001-09-17 23:56:20 +0000278
Georg Brandl61fdd712008-02-02 11:05:00 +0000279 test.test_support.run_unittest(SocketServerTest)
Guido van Rossum39f1b362001-07-10 11:52:38 +0000280
Tim Petersa9f6f222001-09-17 23:56:20 +0000281if __name__ == "__main__":
282 test_main()