blob: 8595e5a2456710df413b79e6f8b7336b3053d49e [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
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:
43 class ForkingUnixStreamServer(SocketServer.ForkingMixIn,
44 SocketServer.UnixStreamServer):
45 pass
Georg Brandl61fdd712008-02-02 11:05:00 +000046
Amaury Forgeot d'Arc72a65762008-02-03 23:57:24 +000047 class ForkingUnixDatagramServer(SocketServer.ForkingMixIn,
48 SocketServer.UnixDatagramServer):
49 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)
60 testcase.assertEquals(pid2, pid)
61 testcase.assertEquals(72 << 8, status)
62
63
Georg Brandl61fdd712008-02-02 11:05:00 +000064class SocketServerTest(unittest.TestCase):
65 """Test all socket servers."""
Guido van Rossum39f1b362001-07-10 11:52:38 +000066
Georg Brandl61fdd712008-02-02 11:05:00 +000067 def setUp(self):
Jeffrey Yasskinf28896d2008-03-05 06:19:56 +000068 signal_alarm(20) # Kill deadlocks after 20 seconds.
Georg Brandl61fdd712008-02-02 11:05:00 +000069 self.port_seed = 0
70 self.test_files = []
Neal Norwitzb476fdf2006-08-15 04:58:28 +000071
Georg Brandl61fdd712008-02-02 11:05:00 +000072 def tearDown(self):
Neal Norwitzacdb6fb2008-03-23 06:16:04 +000073 signal_alarm(0) # Didn't deadlock.
Georg Brandl61fdd712008-02-02 11:05:00 +000074 reap_children()
75
76 for fn in self.test_files:
77 try:
78 os.remove(fn)
79 except os.error:
80 pass
81 self.test_files[:] = []
Georg Brandl61fdd712008-02-02 11:05:00 +000082
83 def pickaddr(self, proto):
84 if proto == socket.AF_INET:
Jeffrey Yasskin180997b2008-02-28 05:53:18 +000085 return (HOST, 0)
Georg Brandl61fdd712008-02-02 11:05:00 +000086 else:
Jeffrey Yasskin180997b2008-02-28 05:53:18 +000087 # XXX: We need a way to tell AF_UNIX to pick its own name
88 # like AF_INET provides port==0.
89 dir = None
90 if os.name == 'os2':
91 dir = '\socket'
92 fn = tempfile.mktemp(prefix='unix_socket.', dir=dir)
Georg Brandl61fdd712008-02-02 11:05:00 +000093 if os.name == 'os2':
94 # AF_UNIX socket names on OS/2 require a specific prefix
95 # which can't include a drive letter and must also use
96 # backslashes as directory separators
97 if fn[1] == ':':
98 fn = fn[2:]
99 if fn[0] in (os.sep, os.altsep):
100 fn = fn[1:]
Georg Brandl61fdd712008-02-02 11:05:00 +0000101 if os.sep == '/':
102 fn = fn.replace(os.sep, os.altsep)
103 else:
104 fn = fn.replace(os.altsep, os.sep)
105 self.test_files.append(fn)
106 return fn
107
Jeffrey Yasskine75f59a2008-03-07 06:22:15 +0000108 def make_server(self, addr, svrcls, hdlrbase):
109 class MyServer(svrcls):
110 def handle_error(self, request, client_address):
111 self.close_request(request)
112 self.server_close()
113 raise
114
Jeffrey Yasskin180997b2008-02-28 05:53:18 +0000115 class MyHandler(hdlrbase):
116 def handle(self):
117 line = self.rfile.readline()
118 self.wfile.write(line)
119
Jeffrey Yasskine75f59a2008-03-07 06:22:15 +0000120 if verbose: print "creating server"
121 server = MyServer(addr, MyHandler)
122 self.assertEquals(server.server_address, server.socket.getsockname())
123 return server
124
125 def run_server(self, svrcls, hdlrbase, testfunc):
126 server = self.make_server(self.pickaddr(svrcls.address_family),
127 svrcls, hdlrbase)
128 # We had the OS pick a port, so pull the real address out of
129 # the server.
130 addr = server.server_address
Jeffrey Yasskin180997b2008-02-28 05:53:18 +0000131 if verbose:
Jeffrey Yasskine75f59a2008-03-07 06:22:15 +0000132 print "server created"
Jeffrey Yasskin180997b2008-02-28 05:53:18 +0000133 print "ADDR =", addr
134 print "CLASS =", svrcls
Jeffrey Yasskine75f59a2008-03-07 06:22:15 +0000135 t = threading.Thread(
136 name='%s serving' % svrcls,
137 target=server.serve_forever,
138 # Short poll interval to make the test finish quickly.
139 # Time between requests is short enough that we won't wake
140 # up spuriously too many times.
141 kwargs={'poll_interval':0.01})
142 t.setDaemon(True) # In case this function raises.
Jeffrey Yasskin180997b2008-02-28 05:53:18 +0000143 t.start()
144 if verbose: print "server running"
Jeffrey Yasskine75f59a2008-03-07 06:22:15 +0000145 for i in range(3):
Jeffrey Yasskin180997b2008-02-28 05:53:18 +0000146 if verbose: print "test client", i
147 testfunc(svrcls.address_family, addr)
148 if verbose: print "waiting for server"
Jeffrey Yasskine75f59a2008-03-07 06:22:15 +0000149 server.shutdown()
Jeffrey Yasskin180997b2008-02-28 05:53:18 +0000150 t.join()
151 if verbose: print "done"
Georg Brandl61fdd712008-02-02 11:05:00 +0000152
153 def stream_examine(self, proto, addr):
154 s = socket.socket(proto, socket.SOCK_STREAM)
155 s.connect(addr)
156 s.sendall(TEST_STR)
157 buf = data = receive(s, 100)
158 while data and '\n' not in buf:
159 data = receive(s, 100)
160 buf += data
161 self.assertEquals(buf, TEST_STR)
162 s.close()
163
164 def dgram_examine(self, proto, addr):
165 s = socket.socket(proto, socket.SOCK_DGRAM)
166 s.sendto(TEST_STR, addr)
167 buf = data = receive(s, 100)
168 while data and '\n' not in buf:
169 data = receive(s, 100)
170 buf += data
171 self.assertEquals(buf, TEST_STR)
172 s.close()
173
Jeffrey Yasskin180997b2008-02-28 05:53:18 +0000174 def test_TCPServer(self):
175 self.run_server(SocketServer.TCPServer,
176 SocketServer.StreamRequestHandler,
177 self.stream_examine)
Georg Brandl61fdd712008-02-02 11:05:00 +0000178
Jeffrey Yasskin180997b2008-02-28 05:53:18 +0000179 def test_ThreadingTCPServer(self):
180 self.run_server(SocketServer.ThreadingTCPServer,
181 SocketServer.StreamRequestHandler,
182 self.stream_examine)
Georg Brandl61fdd712008-02-02 11:05:00 +0000183
Jeffrey Yasskin180997b2008-02-28 05:53:18 +0000184 if HAVE_FORKING:
Jeffrey Yasskin392c1592008-02-28 18:03:15 +0000185 def test_ForkingTCPServer(self):
186 with simple_subprocess(self):
187 self.run_server(SocketServer.ForkingTCPServer,
188 SocketServer.StreamRequestHandler,
189 self.stream_examine)
Jeffrey Yasskin180997b2008-02-28 05:53:18 +0000190
191 if HAVE_UNIX_SOCKETS:
192 def test_UnixStreamServer(self):
193 self.run_server(SocketServer.UnixStreamServer,
194 SocketServer.StreamRequestHandler,
195 self.stream_examine)
196
197 def test_ThreadingUnixStreamServer(self):
198 self.run_server(SocketServer.ThreadingUnixStreamServer,
199 SocketServer.StreamRequestHandler,
200 self.stream_examine)
201
Georg Brandl61fdd712008-02-02 11:05:00 +0000202 if HAVE_FORKING:
Jeffrey Yasskin180997b2008-02-28 05:53:18 +0000203 def test_ForkingUnixStreamServer(self):
Jeffrey Yasskin392c1592008-02-28 18:03:15 +0000204 with simple_subprocess(self):
205 self.run_server(ForkingUnixStreamServer,
206 SocketServer.StreamRequestHandler,
207 self.stream_examine)
Jeffrey Yasskin180997b2008-02-28 05:53:18 +0000208
209 def test_UDPServer(self):
210 self.run_server(SocketServer.UDPServer,
211 SocketServer.DatagramRequestHandler,
212 self.dgram_examine)
213
214 def test_ThreadingUDPServer(self):
215 self.run_server(SocketServer.ThreadingUDPServer,
216 SocketServer.DatagramRequestHandler,
217 self.dgram_examine)
218
219 if HAVE_FORKING:
220 def test_ForkingUDPServer(self):
Jeffrey Yasskin392c1592008-02-28 18:03:15 +0000221 with simple_subprocess(self):
222 self.run_server(SocketServer.ForkingUDPServer,
223 SocketServer.DatagramRequestHandler,
224 self.dgram_examine)
Georg Brandl61fdd712008-02-02 11:05:00 +0000225
226 # Alas, on Linux (at least) recvfrom() doesn't return a meaningful
227 # client address so this cannot work:
228
Jeffrey Yasskin180997b2008-02-28 05:53:18 +0000229 # if HAVE_UNIX_SOCKETS:
230 # def test_UnixDatagramServer(self):
231 # self.run_server(SocketServer.UnixDatagramServer,
232 # SocketServer.DatagramRequestHandler,
233 # self.dgram_examine)
234 #
235 # def test_ThreadingUnixDatagramServer(self):
236 # self.run_server(SocketServer.ThreadingUnixDatagramServer,
237 # SocketServer.DatagramRequestHandler,
238 # self.dgram_examine)
239 #
Georg Brandl61fdd712008-02-02 11:05:00 +0000240 # if HAVE_FORKING:
Jeffrey Yasskin180997b2008-02-28 05:53:18 +0000241 # def test_ForkingUnixDatagramServer(self):
242 # self.run_server(SocketServer.ForkingUnixDatagramServer,
243 # SocketServer.DatagramRequestHandler,
244 # self.dgram_examine)
Georg Brandl61fdd712008-02-02 11:05:00 +0000245
Guido van Rossum39f1b362001-07-10 11:52:38 +0000246
Tim Petersa9f6f222001-09-17 23:56:20 +0000247def test_main():
Tim Petersa9f6f222001-09-17 23:56:20 +0000248 if imp.lock_held():
Georg Brandl61fdd712008-02-02 11:05:00 +0000249 # If the import lock is held, the threads will hang
Tim Petersa9f6f222001-09-17 23:56:20 +0000250 raise TestSkipped("can't run when import lock is held")
251
Georg Brandl61fdd712008-02-02 11:05:00 +0000252 test.test_support.run_unittest(SocketServerTest)
Guido van Rossum39f1b362001-07-10 11:52:38 +0000253
Tim Petersa9f6f222001-09-17 23:56:20 +0000254if __name__ == "__main__":
255 test_main()
Trent Nelson00b53ea2008-03-20 00:58:44 +0000256 signal_alarm(3) # Shutdown shouldn't take more than 3 seconds.