blob: 4f0dd3ee5698cb5f991d9ac3f00c65ee89c0257c [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
Guido van Rossum39f1b362001-07-10 11:52:38 +000012import threading
Georg Brandl61fdd712008-02-02 11:05:00 +000013import unittest
Georg Brandle152a772008-05-24 18:31:28 +000014import SocketServer
Georg Brandl61fdd712008-02-02 11:05:00 +000015
16import test.test_support
Antoine Pitrou8aea0502009-10-27 21:27:24 +000017from test.test_support import reap_children, reap_threads, verbose
Georg Brandl61fdd712008-02-02 11:05:00 +000018
19test.test_support.requires("network")
Guido van Rossum39f1b362001-07-10 11:52:38 +000020
Georg Brandl61fdd712008-02-02 11:05:00 +000021TEST_STR = "hello world\n"
Trent Nelsone41b0062008-04-08 23:47:30 +000022HOST = test.test_support.HOST
Georg Brandl61fdd712008-02-02 11:05:00 +000023
24HAVE_UNIX_SOCKETS = hasattr(socket, "AF_UNIX")
25HAVE_FORKING = hasattr(os, "fork") and os.name != "os2"
26
Jeffrey Yasskinf28896d2008-03-05 06:19:56 +000027def signal_alarm(n):
28 """Call signal.alarm when it exists (i.e. not on Windows)."""
29 if hasattr(signal, 'alarm'):
30 signal.alarm(n)
Guido van Rossum39f1b362001-07-10 11:52:38 +000031
Guido van Rossum39f1b362001-07-10 11:52:38 +000032def receive(sock, n, timeout=20):
33 r, w, x = select.select([sock], [], [], timeout)
34 if sock in r:
35 return sock.recv(n)
36 else:
Walter Dörwald70a6b492004-02-12 17:35:32 +000037 raise RuntimeError, "timed out on %r" % (sock,)
Guido van Rossum39f1b362001-07-10 11:52:38 +000038
Amaury Forgeot d'Arc72a65762008-02-03 23:57:24 +000039if HAVE_UNIX_SOCKETS:
Georg Brandle152a772008-05-24 18:31:28 +000040 class ForkingUnixStreamServer(SocketServer.ForkingMixIn,
41 SocketServer.UnixStreamServer):
Amaury Forgeot d'Arc72a65762008-02-03 23:57:24 +000042 pass
Georg Brandl61fdd712008-02-02 11:05:00 +000043
Georg Brandle152a772008-05-24 18:31:28 +000044 class ForkingUnixDatagramServer(SocketServer.ForkingMixIn,
45 SocketServer.UnixDatagramServer):
Amaury Forgeot d'Arc72a65762008-02-03 23:57:24 +000046 pass
Georg Brandl61fdd712008-02-02 11:05:00 +000047
48
Jeffrey Yasskin392c1592008-02-28 18:03:15 +000049@contextlib.contextmanager
50def simple_subprocess(testcase):
51 pid = os.fork()
52 if pid == 0:
53 # Don't throw an exception; it would be caught by the test harness.
54 os._exit(72)
55 yield None
56 pid2, status = os.waitpid(pid, 0)
57 testcase.assertEquals(pid2, pid)
58 testcase.assertEquals(72 << 8, status)
59
60
Georg Brandl61fdd712008-02-02 11:05:00 +000061class SocketServerTest(unittest.TestCase):
62 """Test all socket servers."""
Guido van Rossum39f1b362001-07-10 11:52:38 +000063
Georg Brandl61fdd712008-02-02 11:05:00 +000064 def setUp(self):
Jeffrey Yasskinf28896d2008-03-05 06:19:56 +000065 signal_alarm(20) # Kill deadlocks after 20 seconds.
Georg Brandl61fdd712008-02-02 11:05:00 +000066 self.port_seed = 0
67 self.test_files = []
Neal Norwitzb476fdf2006-08-15 04:58:28 +000068
Georg Brandl61fdd712008-02-02 11:05:00 +000069 def tearDown(self):
Neal Norwitzacdb6fb2008-03-23 06:16:04 +000070 signal_alarm(0) # Didn't deadlock.
Georg Brandl61fdd712008-02-02 11:05:00 +000071 reap_children()
72
73 for fn in self.test_files:
74 try:
75 os.remove(fn)
76 except os.error:
77 pass
78 self.test_files[:] = []
Georg Brandl61fdd712008-02-02 11:05:00 +000079
80 def pickaddr(self, proto):
81 if proto == socket.AF_INET:
Jeffrey Yasskin180997b2008-02-28 05:53:18 +000082 return (HOST, 0)
Georg Brandl61fdd712008-02-02 11:05:00 +000083 else:
Jeffrey Yasskin180997b2008-02-28 05:53:18 +000084 # XXX: We need a way to tell AF_UNIX to pick its own name
85 # like AF_INET provides port==0.
86 dir = None
87 if os.name == 'os2':
88 dir = '\socket'
89 fn = tempfile.mktemp(prefix='unix_socket.', dir=dir)
Georg Brandl61fdd712008-02-02 11:05:00 +000090 if os.name == 'os2':
91 # AF_UNIX socket names on OS/2 require a specific prefix
92 # which can't include a drive letter and must also use
93 # backslashes as directory separators
94 if fn[1] == ':':
95 fn = fn[2:]
96 if fn[0] in (os.sep, os.altsep):
97 fn = fn[1:]
Georg Brandl61fdd712008-02-02 11:05:00 +000098 if os.sep == '/':
99 fn = fn.replace(os.sep, os.altsep)
100 else:
101 fn = fn.replace(os.altsep, os.sep)
102 self.test_files.append(fn)
103 return fn
104
Jeffrey Yasskine75f59a2008-03-07 06:22:15 +0000105 def make_server(self, addr, svrcls, hdlrbase):
106 class MyServer(svrcls):
107 def handle_error(self, request, client_address):
108 self.close_request(request)
109 self.server_close()
110 raise
111
Jeffrey Yasskin180997b2008-02-28 05:53:18 +0000112 class MyHandler(hdlrbase):
113 def handle(self):
114 line = self.rfile.readline()
115 self.wfile.write(line)
116
Jeffrey Yasskine75f59a2008-03-07 06:22:15 +0000117 if verbose: print "creating server"
118 server = MyServer(addr, MyHandler)
119 self.assertEquals(server.server_address, server.socket.getsockname())
120 return server
121
Antoine Pitrou8aea0502009-10-27 21:27:24 +0000122 @reap_threads
Jeffrey Yasskine75f59a2008-03-07 06:22:15 +0000123 def run_server(self, svrcls, hdlrbase, testfunc):
124 server = self.make_server(self.pickaddr(svrcls.address_family),
125 svrcls, hdlrbase)
126 # We had the OS pick a port, so pull the real address out of
127 # the server.
128 addr = server.server_address
Jeffrey Yasskin180997b2008-02-28 05:53:18 +0000129 if verbose:
Jeffrey Yasskine75f59a2008-03-07 06:22:15 +0000130 print "server created"
Jeffrey Yasskin180997b2008-02-28 05:53:18 +0000131 print "ADDR =", addr
132 print "CLASS =", svrcls
Jeffrey Yasskine75f59a2008-03-07 06:22:15 +0000133 t = threading.Thread(
134 name='%s serving' % svrcls,
135 target=server.serve_forever,
136 # Short poll interval to make the test finish quickly.
137 # Time between requests is short enough that we won't wake
138 # up spuriously too many times.
139 kwargs={'poll_interval':0.01})
Benjamin Petersona9b22222008-08-18 18:01:43 +0000140 t.daemon = True # In case this function raises.
Jeffrey Yasskin180997b2008-02-28 05:53:18 +0000141 t.start()
142 if verbose: print "server running"
Jeffrey Yasskine75f59a2008-03-07 06:22:15 +0000143 for i in range(3):
Jeffrey Yasskin180997b2008-02-28 05:53:18 +0000144 if verbose: print "test client", i
145 testfunc(svrcls.address_family, addr)
146 if verbose: print "waiting for server"
Jeffrey Yasskine75f59a2008-03-07 06:22:15 +0000147 server.shutdown()
Jeffrey Yasskin180997b2008-02-28 05:53:18 +0000148 t.join()
149 if verbose: print "done"
Georg Brandl61fdd712008-02-02 11:05:00 +0000150
151 def stream_examine(self, proto, addr):
152 s = socket.socket(proto, socket.SOCK_STREAM)
153 s.connect(addr)
154 s.sendall(TEST_STR)
155 buf = data = receive(s, 100)
156 while data and '\n' not in buf:
157 data = receive(s, 100)
158 buf += data
159 self.assertEquals(buf, TEST_STR)
160 s.close()
161
162 def dgram_examine(self, proto, addr):
163 s = socket.socket(proto, socket.SOCK_DGRAM)
164 s.sendto(TEST_STR, addr)
165 buf = data = receive(s, 100)
166 while data and '\n' not in buf:
167 data = receive(s, 100)
168 buf += data
169 self.assertEquals(buf, TEST_STR)
170 s.close()
171
Jeffrey Yasskin180997b2008-02-28 05:53:18 +0000172 def test_TCPServer(self):
Georg Brandle152a772008-05-24 18:31:28 +0000173 self.run_server(SocketServer.TCPServer,
174 SocketServer.StreamRequestHandler,
Jeffrey Yasskin180997b2008-02-28 05:53:18 +0000175 self.stream_examine)
Georg Brandl61fdd712008-02-02 11:05:00 +0000176
Jeffrey Yasskin180997b2008-02-28 05:53:18 +0000177 def test_ThreadingTCPServer(self):
Georg Brandle152a772008-05-24 18:31:28 +0000178 self.run_server(SocketServer.ThreadingTCPServer,
179 SocketServer.StreamRequestHandler,
Jeffrey Yasskin180997b2008-02-28 05:53:18 +0000180 self.stream_examine)
Georg Brandl61fdd712008-02-02 11:05:00 +0000181
Jeffrey Yasskin180997b2008-02-28 05:53:18 +0000182 if HAVE_FORKING:
Jeffrey Yasskin392c1592008-02-28 18:03:15 +0000183 def test_ForkingTCPServer(self):
184 with simple_subprocess(self):
Georg Brandle152a772008-05-24 18:31:28 +0000185 self.run_server(SocketServer.ForkingTCPServer,
186 SocketServer.StreamRequestHandler,
Jeffrey Yasskin392c1592008-02-28 18:03:15 +0000187 self.stream_examine)
Jeffrey Yasskin180997b2008-02-28 05:53:18 +0000188
189 if HAVE_UNIX_SOCKETS:
190 def test_UnixStreamServer(self):
Georg Brandle152a772008-05-24 18:31:28 +0000191 self.run_server(SocketServer.UnixStreamServer,
192 SocketServer.StreamRequestHandler,
Jeffrey Yasskin180997b2008-02-28 05:53:18 +0000193 self.stream_examine)
194
195 def test_ThreadingUnixStreamServer(self):
Georg Brandle152a772008-05-24 18:31:28 +0000196 self.run_server(SocketServer.ThreadingUnixStreamServer,
197 SocketServer.StreamRequestHandler,
Jeffrey Yasskin180997b2008-02-28 05:53:18 +0000198 self.stream_examine)
199
Georg Brandl61fdd712008-02-02 11:05:00 +0000200 if HAVE_FORKING:
Jeffrey Yasskin180997b2008-02-28 05:53:18 +0000201 def test_ForkingUnixStreamServer(self):
Jeffrey Yasskin392c1592008-02-28 18:03:15 +0000202 with simple_subprocess(self):
203 self.run_server(ForkingUnixStreamServer,
Georg Brandle152a772008-05-24 18:31:28 +0000204 SocketServer.StreamRequestHandler,
Jeffrey Yasskin392c1592008-02-28 18:03:15 +0000205 self.stream_examine)
Jeffrey Yasskin180997b2008-02-28 05:53:18 +0000206
207 def test_UDPServer(self):
Georg Brandle152a772008-05-24 18:31:28 +0000208 self.run_server(SocketServer.UDPServer,
209 SocketServer.DatagramRequestHandler,
Jeffrey Yasskin180997b2008-02-28 05:53:18 +0000210 self.dgram_examine)
211
212 def test_ThreadingUDPServer(self):
Georg Brandle152a772008-05-24 18:31:28 +0000213 self.run_server(SocketServer.ThreadingUDPServer,
214 SocketServer.DatagramRequestHandler,
Jeffrey Yasskin180997b2008-02-28 05:53:18 +0000215 self.dgram_examine)
216
217 if HAVE_FORKING:
218 def test_ForkingUDPServer(self):
Jeffrey Yasskin392c1592008-02-28 18:03:15 +0000219 with simple_subprocess(self):
Georg Brandle152a772008-05-24 18:31:28 +0000220 self.run_server(SocketServer.ForkingUDPServer,
221 SocketServer.DatagramRequestHandler,
Jeffrey Yasskin392c1592008-02-28 18:03:15 +0000222 self.dgram_examine)
Georg Brandl61fdd712008-02-02 11:05:00 +0000223
224 # Alas, on Linux (at least) recvfrom() doesn't return a meaningful
225 # client address so this cannot work:
226
Jeffrey Yasskin180997b2008-02-28 05:53:18 +0000227 # if HAVE_UNIX_SOCKETS:
228 # def test_UnixDatagramServer(self):
Georg Brandle152a772008-05-24 18:31:28 +0000229 # self.run_server(SocketServer.UnixDatagramServer,
230 # SocketServer.DatagramRequestHandler,
Jeffrey Yasskin180997b2008-02-28 05:53:18 +0000231 # self.dgram_examine)
232 #
233 # def test_ThreadingUnixDatagramServer(self):
Georg Brandle152a772008-05-24 18:31:28 +0000234 # self.run_server(SocketServer.ThreadingUnixDatagramServer,
235 # SocketServer.DatagramRequestHandler,
Jeffrey Yasskin180997b2008-02-28 05:53:18 +0000236 # self.dgram_examine)
237 #
Georg Brandl61fdd712008-02-02 11:05:00 +0000238 # if HAVE_FORKING:
Jeffrey Yasskin180997b2008-02-28 05:53:18 +0000239 # def test_ForkingUnixDatagramServer(self):
Georg Brandle152a772008-05-24 18:31:28 +0000240 # self.run_server(SocketServer.ForkingUnixDatagramServer,
241 # SocketServer.DatagramRequestHandler,
Jeffrey Yasskin180997b2008-02-28 05:53:18 +0000242 # self.dgram_examine)
Georg Brandl61fdd712008-02-02 11:05:00 +0000243
Antoine Pitroua6240402010-04-25 21:40:32 +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()
268
Guido van Rossum39f1b362001-07-10 11:52:38 +0000269
Tim Petersa9f6f222001-09-17 23:56:20 +0000270def test_main():
Tim Petersa9f6f222001-09-17 23:56:20 +0000271 if imp.lock_held():
Georg Brandl61fdd712008-02-02 11:05:00 +0000272 # If the import lock is held, the threads will hang
Benjamin Petersonbec087f2009-03-26 21:10:30 +0000273 raise unittest.SkipTest("can't run when import lock is held")
Tim Petersa9f6f222001-09-17 23:56:20 +0000274
Georg Brandl61fdd712008-02-02 11:05:00 +0000275 test.test_support.run_unittest(SocketServerTest)
Guido van Rossum39f1b362001-07-10 11:52:38 +0000276
Tim Petersa9f6f222001-09-17 23:56:20 +0000277if __name__ == "__main__":
278 test_main()
Trent Nelson00b53ea2008-03-20 00:58:44 +0000279 signal_alarm(3) # Shutdown shouldn't take more than 3 seconds.