blob: 98a4c1f9afd3bcf5bcf5a2e81f87e1c4fc2253ae [file] [log] [blame]
Georg Brandl61fdd712008-02-02 11:05:00 +00001"""
2Test suite for SocketServer.py.
3"""
Guido van Rossum39f1b362001-07-10 11:52:38 +00004
Jeffrey Yasskin392c1592008-02-28 18:03:15 +00005import contextlib
Neal Norwitz909eb122006-06-12 02:13:21 +00006import errno
Georg Brandl61fdd712008-02-02 11:05:00 +00007import imp
Jeffrey Yasskin180997b2008-02-28 05:53:18 +00008import os
Guido van Rossum39f1b362001-07-10 11:52:38 +00009import select
Jeffrey Yasskin180997b2008-02-28 05:53:18 +000010import signal
11import socket
12import tempfile
Guido van Rossum39f1b362001-07-10 11:52:38 +000013import threading
Jeffrey Yasskin180997b2008-02-28 05:53:18 +000014import time
Georg Brandl61fdd712008-02-02 11:05:00 +000015import unittest
16import SocketServer
17
18import test.test_support
19from test.test_support import reap_children, verbose, TestSkipped
20from test.test_support import TESTFN as TEST_FILE
21
22test.test_support.requires("network")
Guido van Rossum39f1b362001-07-10 11:52:38 +000023
24NREQ = 3
Georg Brandl61fdd712008-02-02 11:05:00 +000025TEST_STR = "hello world\n"
26HOST = "localhost"
27
28HAVE_UNIX_SOCKETS = hasattr(socket, "AF_UNIX")
29HAVE_FORKING = hasattr(os, "fork") and os.name != "os2"
30
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:
40 class ForkingUnixStreamServer(SocketServer.ForkingMixIn,
41 SocketServer.UnixStreamServer):
42 pass
Georg Brandl61fdd712008-02-02 11:05:00 +000043
Amaury Forgeot d'Arc72a65762008-02-03 23:57:24 +000044 class ForkingUnixDatagramServer(SocketServer.ForkingMixIn,
45 SocketServer.UnixDatagramServer):
46 pass
Georg Brandl61fdd712008-02-02 11:05:00 +000047
48
49class MyMixinServer:
50 def serve_a_few(self):
51 for i in range(NREQ):
52 self.handle_request()
53
54 def handle_error(self, request, client_address):
55 self.close_request(request)
56 self.server_close()
57 raise
58
Guido van Rossum39f1b362001-07-10 11:52:38 +000059
60class ServerThread(threading.Thread):
61 def __init__(self, addr, svrcls, hdlrcls):
62 threading.Thread.__init__(self)
63 self.__addr = addr
64 self.__svrcls = svrcls
65 self.__hdlrcls = hdlrcls
Guido van Rossumb1bb01e2007-04-04 17:43:02 +000066 self.ready = threading.Event()
Georg Brandl61fdd712008-02-02 11:05:00 +000067
Guido van Rossum39f1b362001-07-10 11:52:38 +000068 def run(self):
69 class svrcls(MyMixinServer, self.__svrcls):
70 pass
71 if verbose: print "thread: creating server"
72 svr = svrcls(self.__addr, self.__hdlrcls)
Jeffrey Yasskin180997b2008-02-28 05:53:18 +000073 # We had the OS pick a port, so pull the real address out of
74 # the server.
75 self.addr = svr.server_address
76 self.port = self.addr[1]
77 if self.addr != svr.socket.getsockname():
78 raise RuntimeError('server_address was %s, expected %s' %
79 (self.addr, svr.socket.getsockname()))
Guido van Rossumb1bb01e2007-04-04 17:43:02 +000080 self.ready.set()
Guido van Rossum39f1b362001-07-10 11:52:38 +000081 if verbose: print "thread: serving three times"
82 svr.serve_a_few()
83 if verbose: print "thread: done"
84
Guido van Rossum39f1b362001-07-10 11:52:38 +000085
Jeffrey Yasskin392c1592008-02-28 18:03:15 +000086@contextlib.contextmanager
87def simple_subprocess(testcase):
88 pid = os.fork()
89 if pid == 0:
90 # Don't throw an exception; it would be caught by the test harness.
91 os._exit(72)
92 yield None
93 pid2, status = os.waitpid(pid, 0)
94 testcase.assertEquals(pid2, pid)
95 testcase.assertEquals(72 << 8, status)
96
97
Georg Brandl61fdd712008-02-02 11:05:00 +000098class SocketServerTest(unittest.TestCase):
99 """Test all socket servers."""
Guido van Rossum39f1b362001-07-10 11:52:38 +0000100
Georg Brandl61fdd712008-02-02 11:05:00 +0000101 def setUp(self):
Jeffrey Yasskin180997b2008-02-28 05:53:18 +0000102 signal.alarm(20) # Kill deadlocks after 20 seconds.
Georg Brandl61fdd712008-02-02 11:05:00 +0000103 self.port_seed = 0
104 self.test_files = []
Neal Norwitzb476fdf2006-08-15 04:58:28 +0000105
Georg Brandl61fdd712008-02-02 11:05:00 +0000106 def tearDown(self):
107 reap_children()
108
109 for fn in self.test_files:
110 try:
111 os.remove(fn)
112 except os.error:
113 pass
114 self.test_files[:] = []
Jeffrey Yasskin180997b2008-02-28 05:53:18 +0000115 signal.alarm(0) # Didn't deadlock.
Georg Brandl61fdd712008-02-02 11:05:00 +0000116
117 def pickaddr(self, proto):
118 if proto == socket.AF_INET:
Jeffrey Yasskin180997b2008-02-28 05:53:18 +0000119 return (HOST, 0)
Georg Brandl61fdd712008-02-02 11:05:00 +0000120 else:
Jeffrey Yasskin180997b2008-02-28 05:53:18 +0000121 # XXX: We need a way to tell AF_UNIX to pick its own name
122 # like AF_INET provides port==0.
123 dir = None
124 if os.name == 'os2':
125 dir = '\socket'
126 fn = tempfile.mktemp(prefix='unix_socket.', dir=dir)
Georg Brandl61fdd712008-02-02 11:05:00 +0000127 if os.name == 'os2':
128 # AF_UNIX socket names on OS/2 require a specific prefix
129 # which can't include a drive letter and must also use
130 # backslashes as directory separators
131 if fn[1] == ':':
132 fn = fn[2:]
133 if fn[0] in (os.sep, os.altsep):
134 fn = fn[1:]
Georg Brandl61fdd712008-02-02 11:05:00 +0000135 if os.sep == '/':
136 fn = fn.replace(os.sep, os.altsep)
137 else:
138 fn = fn.replace(os.altsep, os.sep)
139 self.test_files.append(fn)
140 return fn
141
Jeffrey Yasskin180997b2008-02-28 05:53:18 +0000142 def run_server(self, svrcls, hdlrbase, testfunc):
143 class MyHandler(hdlrbase):
144 def handle(self):
145 line = self.rfile.readline()
146 self.wfile.write(line)
147
148 addr = self.pickaddr(svrcls.address_family)
149 if verbose:
150 print "ADDR =", addr
151 print "CLASS =", svrcls
152 t = ServerThread(addr, svrcls, MyHandler)
153 if verbose: print "server created"
154 t.start()
155 if verbose: print "server running"
156 t.ready.wait(10)
157 self.assert_(t.ready.isSet(),
158 "%s not ready within a reasonable time" % svrcls)
159 addr = t.addr
160 for i in range(NREQ):
161 if verbose: print "test client", i
162 testfunc(svrcls.address_family, addr)
163 if verbose: print "waiting for server"
164 t.join()
165 if verbose: print "done"
Georg Brandl61fdd712008-02-02 11:05:00 +0000166
167 def stream_examine(self, proto, addr):
168 s = socket.socket(proto, socket.SOCK_STREAM)
169 s.connect(addr)
170 s.sendall(TEST_STR)
171 buf = data = receive(s, 100)
172 while data and '\n' not in buf:
173 data = receive(s, 100)
174 buf += data
175 self.assertEquals(buf, TEST_STR)
176 s.close()
177
178 def dgram_examine(self, proto, addr):
179 s = socket.socket(proto, socket.SOCK_DGRAM)
180 s.sendto(TEST_STR, addr)
181 buf = data = receive(s, 100)
182 while data and '\n' not in buf:
183 data = receive(s, 100)
184 buf += data
185 self.assertEquals(buf, TEST_STR)
186 s.close()
187
Jeffrey Yasskin180997b2008-02-28 05:53:18 +0000188 def test_TCPServer(self):
189 self.run_server(SocketServer.TCPServer,
190 SocketServer.StreamRequestHandler,
191 self.stream_examine)
Georg Brandl61fdd712008-02-02 11:05:00 +0000192
Jeffrey Yasskin180997b2008-02-28 05:53:18 +0000193 def test_ThreadingTCPServer(self):
194 self.run_server(SocketServer.ThreadingTCPServer,
195 SocketServer.StreamRequestHandler,
196 self.stream_examine)
Georg Brandl61fdd712008-02-02 11:05:00 +0000197
Jeffrey Yasskin180997b2008-02-28 05:53:18 +0000198 if HAVE_FORKING:
Jeffrey Yasskin392c1592008-02-28 18:03:15 +0000199 def test_ForkingTCPServer(self):
200 with simple_subprocess(self):
201 self.run_server(SocketServer.ForkingTCPServer,
202 SocketServer.StreamRequestHandler,
203 self.stream_examine)
Jeffrey Yasskin180997b2008-02-28 05:53:18 +0000204
205 if HAVE_UNIX_SOCKETS:
206 def test_UnixStreamServer(self):
207 self.run_server(SocketServer.UnixStreamServer,
208 SocketServer.StreamRequestHandler,
209 self.stream_examine)
210
211 def test_ThreadingUnixStreamServer(self):
212 self.run_server(SocketServer.ThreadingUnixStreamServer,
213 SocketServer.StreamRequestHandler,
214 self.stream_examine)
215
Georg Brandl61fdd712008-02-02 11:05:00 +0000216 if HAVE_FORKING:
Jeffrey Yasskin180997b2008-02-28 05:53:18 +0000217 def test_ForkingUnixStreamServer(self):
Jeffrey Yasskin392c1592008-02-28 18:03:15 +0000218 with simple_subprocess(self):
219 self.run_server(ForkingUnixStreamServer,
220 SocketServer.StreamRequestHandler,
221 self.stream_examine)
Jeffrey Yasskin180997b2008-02-28 05:53:18 +0000222
223 def test_UDPServer(self):
224 self.run_server(SocketServer.UDPServer,
225 SocketServer.DatagramRequestHandler,
226 self.dgram_examine)
227
228 def test_ThreadingUDPServer(self):
229 self.run_server(SocketServer.ThreadingUDPServer,
230 SocketServer.DatagramRequestHandler,
231 self.dgram_examine)
232
233 if HAVE_FORKING:
234 def test_ForkingUDPServer(self):
Jeffrey Yasskin392c1592008-02-28 18:03:15 +0000235 with simple_subprocess(self):
236 self.run_server(SocketServer.ForkingUDPServer,
237 SocketServer.DatagramRequestHandler,
238 self.dgram_examine)
Georg Brandl61fdd712008-02-02 11:05:00 +0000239
240 # Alas, on Linux (at least) recvfrom() doesn't return a meaningful
241 # client address so this cannot work:
242
Jeffrey Yasskin180997b2008-02-28 05:53:18 +0000243 # if HAVE_UNIX_SOCKETS:
244 # def test_UnixDatagramServer(self):
245 # self.run_server(SocketServer.UnixDatagramServer,
246 # SocketServer.DatagramRequestHandler,
247 # self.dgram_examine)
248 #
249 # def test_ThreadingUnixDatagramServer(self):
250 # self.run_server(SocketServer.ThreadingUnixDatagramServer,
251 # SocketServer.DatagramRequestHandler,
252 # self.dgram_examine)
253 #
Georg Brandl61fdd712008-02-02 11:05:00 +0000254 # if HAVE_FORKING:
Jeffrey Yasskin180997b2008-02-28 05:53:18 +0000255 # def test_ForkingUnixDatagramServer(self):
256 # self.run_server(SocketServer.ForkingUnixDatagramServer,
257 # SocketServer.DatagramRequestHandler,
258 # self.dgram_examine)
Georg Brandl61fdd712008-02-02 11:05:00 +0000259
Guido van Rossum39f1b362001-07-10 11:52:38 +0000260
Tim Petersa9f6f222001-09-17 23:56:20 +0000261def test_main():
Tim Petersa9f6f222001-09-17 23:56:20 +0000262 if imp.lock_held():
Georg Brandl61fdd712008-02-02 11:05:00 +0000263 # If the import lock is held, the threads will hang
Tim Petersa9f6f222001-09-17 23:56:20 +0000264 raise TestSkipped("can't run when import lock is held")
265
Georg Brandl61fdd712008-02-02 11:05:00 +0000266 test.test_support.run_unittest(SocketServerTest)
Guido van Rossum39f1b362001-07-10 11:52:38 +0000267
Tim Petersa9f6f222001-09-17 23:56:20 +0000268if __name__ == "__main__":
269 test_main()
Jeffrey Yasskin180997b2008-02-28 05:53:18 +0000270 signal.alarm(3) # Shutdown shouldn't take more than 3 seconds.