blob: a38e0fd64f1d9a5701ea777e9d713a825c534f3c [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
Guido van Rossum39f1b362001-07-10 11:52:38 +000012import threading
Christian Heimes292d3512008-02-03 16:51:08 +000013import unittest
Alexandre Vassalottice261952008-05-12 02:31:37 +000014import socketserver
Christian Heimes292d3512008-02-03 16:51:08 +000015
Benjamin Petersonee8712c2008-05-20 21:35:26 +000016import test.support
Antoine Pitrouc00d4b42009-10-27 21:32:38 +000017from test.support import reap_children, reap_threads, verbose
Christian Heimes292d3512008-02-03 16:51:08 +000018
Benjamin Petersonee8712c2008-05-20 21:35:26 +000019test.support.requires("network")
Guido van Rossum39f1b362001-07-10 11:52:38 +000020
Christian Heimes292d3512008-02-03 16:51:08 +000021TEST_STR = b"hello world\n"
Benjamin Petersonee8712c2008-05-20 21:35:26 +000022HOST = test.support.HOST
Christian Heimes292d3512008-02-03 16:51:08 +000023
24HAVE_UNIX_SOCKETS = hasattr(socket, "AF_UNIX")
25HAVE_FORKING = hasattr(os, "fork") and os.name != "os2"
26
Christian Heimesdd15f6c2008-03-16 00:07:10 +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
Christian Heimes292d3512008-02-03 16:51:08 +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:
37 raise RuntimeError("timed out on %r" % (sock,))
38
Christian Heimes15ebc882008-02-04 18:48:49 +000039if HAVE_UNIX_SOCKETS:
Alexandre Vassalottice261952008-05-12 02:31:37 +000040 class ForkingUnixStreamServer(socketserver.ForkingMixIn,
41 socketserver.UnixStreamServer):
Christian Heimes15ebc882008-02-04 18:48:49 +000042 pass
Christian Heimes292d3512008-02-03 16:51:08 +000043
Alexandre Vassalottice261952008-05-12 02:31:37 +000044 class ForkingUnixDatagramServer(socketserver.ForkingMixIn,
45 socketserver.UnixDatagramServer):
Christian Heimes15ebc882008-02-04 18:48:49 +000046 pass
Christian Heimes292d3512008-02-03 16:51:08 +000047
48
Christian Heimes70e7ea22008-02-28 20:02:27 +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
Christian Heimes292d3512008-02-03 16:51:08 +000061class SocketServerTest(unittest.TestCase):
62 """Test all socket servers."""
Guido van Rossum39f1b362001-07-10 11:52:38 +000063
Christian Heimes292d3512008-02-03 16:51:08 +000064 def setUp(self):
Christian Heimesdd15f6c2008-03-16 00:07:10 +000065 signal_alarm(20) # Kill deadlocks after 20 seconds.
Christian Heimes292d3512008-02-03 16:51:08 +000066 self.port_seed = 0
67 self.test_files = []
Guido van Rossum39f1b362001-07-10 11:52:38 +000068
Christian Heimes292d3512008-02-03 16:51:08 +000069 def tearDown(self):
Christian Heimesfe337bf2008-03-23 21:54:12 +000070 signal_alarm(0) # Didn't deadlock.
Christian Heimes292d3512008-02-03 16:51:08 +000071 reap_children()
Thomas Wouters00ee7ba2006-08-21 19:07:27 +000072
Christian Heimes292d3512008-02-03 16:51:08 +000073 for fn in self.test_files:
74 try:
75 os.remove(fn)
76 except os.error:
77 pass
78 self.test_files[:] = []
Christian Heimes292d3512008-02-03 16:51:08 +000079
80 def pickaddr(self, proto):
81 if proto == socket.AF_INET:
Christian Heimes9e7f1d22008-02-28 12:27:11 +000082 return (HOST, 0)
Christian Heimes292d3512008-02-03 16:51:08 +000083 else:
Christian Heimes9e7f1d22008-02-28 12:27:11 +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)
Christian Heimes292d3512008-02-03 16:51:08 +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:]
Christian Heimes292d3512008-02-03 16:51:08 +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
Christian Heimesdd15f6c2008-03-16 00:07:10 +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
Christian Heimes9e7f1d22008-02-28 12:27:11 +0000111
Christian Heimes9e7f1d22008-02-28 12:27:11 +0000112 class MyHandler(hdlrbase):
113 def handle(self):
114 line = self.rfile.readline()
115 self.wfile.write(line)
116
Christian Heimesdd15f6c2008-03-16 00:07:10 +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 Pitrouc00d4b42009-10-27 21:32:38 +0000122 @reap_threads
Christian Heimesdd15f6c2008-03-16 00:07:10 +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
Christian Heimes9e7f1d22008-02-28 12:27:11 +0000129 if verbose:
130 print("ADDR =", addr)
131 print("CLASS =", svrcls)
Christian Heimesdd15f6c2008-03-16 00:07:10 +0000132
133 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 Peterson72753702008-08-18 18:09:21 +0000140 t.daemon = True # In case this function raises.
Christian Heimes9e7f1d22008-02-28 12:27:11 +0000141 t.start()
142 if verbose: print("server running")
Christian Heimesdd15f6c2008-03-16 00:07:10 +0000143 for i in range(3):
Christian Heimes9e7f1d22008-02-28 12:27:11 +0000144 if verbose: print("test client", i)
145 testfunc(svrcls.address_family, addr)
146 if verbose: print("waiting for server")
Christian Heimesdd15f6c2008-03-16 00:07:10 +0000147 server.shutdown()
Christian Heimes9e7f1d22008-02-28 12:27:11 +0000148 t.join()
149 if verbose: print("done")
Christian Heimes292d3512008-02-03 16:51:08 +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)
Christian Heimesfdb6bb52008-02-03 17:32:13 +0000156 while data and b'\n' not in buf:
Christian Heimes292d3512008-02-03 16:51:08 +0000157 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)
Christian Heimesfdb6bb52008-02-03 17:32:13 +0000166 while data and b'\n' not in buf:
Christian Heimes292d3512008-02-03 16:51:08 +0000167 data = receive(s, 100)
168 buf += data
169 self.assertEquals(buf, TEST_STR)
170 s.close()
171
Christian Heimes9e7f1d22008-02-28 12:27:11 +0000172 def test_TCPServer(self):
Alexandre Vassalottice261952008-05-12 02:31:37 +0000173 self.run_server(socketserver.TCPServer,
174 socketserver.StreamRequestHandler,
Christian Heimes9e7f1d22008-02-28 12:27:11 +0000175 self.stream_examine)
Christian Heimes292d3512008-02-03 16:51:08 +0000176
Christian Heimes9e7f1d22008-02-28 12:27:11 +0000177 def test_ThreadingTCPServer(self):
Alexandre Vassalottice261952008-05-12 02:31:37 +0000178 self.run_server(socketserver.ThreadingTCPServer,
179 socketserver.StreamRequestHandler,
Christian Heimes9e7f1d22008-02-28 12:27:11 +0000180 self.stream_examine)
Christian Heimes292d3512008-02-03 16:51:08 +0000181
Christian Heimes9e7f1d22008-02-28 12:27:11 +0000182 if HAVE_FORKING:
Christian Heimes70e7ea22008-02-28 20:02:27 +0000183 def test_ForkingTCPServer(self):
184 with simple_subprocess(self):
Alexandre Vassalottice261952008-05-12 02:31:37 +0000185 self.run_server(socketserver.ForkingTCPServer,
186 socketserver.StreamRequestHandler,
Christian Heimes70e7ea22008-02-28 20:02:27 +0000187 self.stream_examine)
Christian Heimes9e7f1d22008-02-28 12:27:11 +0000188
189 if HAVE_UNIX_SOCKETS:
190 def test_UnixStreamServer(self):
Alexandre Vassalottice261952008-05-12 02:31:37 +0000191 self.run_server(socketserver.UnixStreamServer,
192 socketserver.StreamRequestHandler,
Christian Heimes9e7f1d22008-02-28 12:27:11 +0000193 self.stream_examine)
194
195 def test_ThreadingUnixStreamServer(self):
Alexandre Vassalottice261952008-05-12 02:31:37 +0000196 self.run_server(socketserver.ThreadingUnixStreamServer,
197 socketserver.StreamRequestHandler,
Christian Heimes9e7f1d22008-02-28 12:27:11 +0000198 self.stream_examine)
199
Christian Heimes292d3512008-02-03 16:51:08 +0000200 if HAVE_FORKING:
Christian Heimes9e7f1d22008-02-28 12:27:11 +0000201 def test_ForkingUnixStreamServer(self):
Christian Heimes70e7ea22008-02-28 20:02:27 +0000202 with simple_subprocess(self):
203 self.run_server(ForkingUnixStreamServer,
Alexandre Vassalottice261952008-05-12 02:31:37 +0000204 socketserver.StreamRequestHandler,
Christian Heimes70e7ea22008-02-28 20:02:27 +0000205 self.stream_examine)
Christian Heimes9e7f1d22008-02-28 12:27:11 +0000206
207 def test_UDPServer(self):
Alexandre Vassalottice261952008-05-12 02:31:37 +0000208 self.run_server(socketserver.UDPServer,
209 socketserver.DatagramRequestHandler,
Christian Heimes9e7f1d22008-02-28 12:27:11 +0000210 self.dgram_examine)
211
212 def test_ThreadingUDPServer(self):
Alexandre Vassalottice261952008-05-12 02:31:37 +0000213 self.run_server(socketserver.ThreadingUDPServer,
214 socketserver.DatagramRequestHandler,
Christian Heimes9e7f1d22008-02-28 12:27:11 +0000215 self.dgram_examine)
216
217 if HAVE_FORKING:
218 def test_ForkingUDPServer(self):
Christian Heimes70e7ea22008-02-28 20:02:27 +0000219 with simple_subprocess(self):
Alexandre Vassalottice261952008-05-12 02:31:37 +0000220 self.run_server(socketserver.ForkingUDPServer,
221 socketserver.DatagramRequestHandler,
Christian Heimes70e7ea22008-02-28 20:02:27 +0000222 self.dgram_examine)
Christian Heimes292d3512008-02-03 16:51:08 +0000223
224 # Alas, on Linux (at least) recvfrom() doesn't return a meaningful
225 # client address so this cannot work:
226
Christian Heimes9e7f1d22008-02-28 12:27:11 +0000227 # if HAVE_UNIX_SOCKETS:
228 # def test_UnixDatagramServer(self):
Alexandre Vassalottice261952008-05-12 02:31:37 +0000229 # self.run_server(socketserver.UnixDatagramServer,
230 # socketserver.DatagramRequestHandler,
Christian Heimes9e7f1d22008-02-28 12:27:11 +0000231 # self.dgram_examine)
232 #
233 # def test_ThreadingUnixDatagramServer(self):
Alexandre Vassalottice261952008-05-12 02:31:37 +0000234 # self.run_server(socketserver.ThreadingUnixDatagramServer,
235 # socketserver.DatagramRequestHandler,
Christian Heimes9e7f1d22008-02-28 12:27:11 +0000236 # self.dgram_examine)
237 #
Christian Heimes292d3512008-02-03 16:51:08 +0000238 # if HAVE_FORKING:
Christian Heimes9e7f1d22008-02-28 12:27:11 +0000239 # def test_ForkingUnixDatagramServer(self):
Alexandre Vassalottice261952008-05-12 02:31:37 +0000240 # self.run_server(socketserver.ForkingUnixDatagramServer,
241 # socketserver.DatagramRequestHandler,
Christian Heimes9e7f1d22008-02-28 12:27:11 +0000242 # self.dgram_examine)
Christian Heimes292d3512008-02-03 16:51:08 +0000243
Guido van Rossum39f1b362001-07-10 11:52:38 +0000244
Tim Petersa9f6f222001-09-17 23:56:20 +0000245def test_main():
Tim Petersa9f6f222001-09-17 23:56:20 +0000246 if imp.lock_held():
Christian Heimes292d3512008-02-03 16:51:08 +0000247 # If the import lock is held, the threads will hang
Benjamin Petersone549ead2009-03-28 21:42:05 +0000248 raise unittest.SkipTest("can't run when import lock is held")
Tim Petersa9f6f222001-09-17 23:56:20 +0000249
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000250 test.support.run_unittest(SocketServerTest)
Guido van Rossum39f1b362001-07-10 11:52:38 +0000251
Tim Petersa9f6f222001-09-17 23:56:20 +0000252if __name__ == "__main__":
253 test_main()
Christian Heimesdd15f6c2008-03-16 00:07:10 +0000254 signal_alarm(3) # Shutdown shouldn't take more than 3 seconds.