1292d351fc1a7dc9feccd412843832808680a631fChristian Heimes"""
2ce261952e640b2d09ada1b160f0cfa37db32f928Alexandre VassalottiTest suite for socketserver.
3292d351fc1a7dc9feccd412843832808680a631fChristian Heimes"""
439f1b3656ed1fdd98d908a21e1b0aafa6b4e75c4Guido van Rossum
570e7ea23f18aacc31f429787645ff8c074c0ad86Christian Heimesimport contextlib
634eeed42901666fce099947f93dfdfc05411f286Martin Panterimport io
79e7f1d2e965400edcb2c0cb7fee625ef2b595eb5Christian Heimesimport os
839f1b3656ed1fdd98d908a21e1b0aafa6b4e75c4Guido van Rossumimport select
99e7f1d2e965400edcb2c0cb7fee625ef2b595eb5Christian Heimesimport signal
109e7f1d2e965400edcb2c0cb7fee625ef2b595eb5Christian Heimesimport socket
119e7f1d2e965400edcb2c0cb7fee625ef2b595eb5Christian Heimesimport tempfile
12292d351fc1a7dc9feccd412843832808680a631fChristian Heimesimport unittest
13ce261952e640b2d09ada1b160f0cfa37db32f928Alexandre Vassalottiimport socketserver
14292d351fc1a7dc9feccd412843832808680a631fChristian Heimes
15ee8712cda46338d223509cc5751fd36509ad3860Benjamin Petersonimport test.support
16c00d4b437d544268b699fc57fe9e7c57ae89f1b3Antoine Pitroufrom test.support import reap_children, reap_threads, verbose
1745df820591c319061a625bdd99d7bbd2a26f8117Victor Stinnertry:
1845df820591c319061a625bdd99d7bbd2a26f8117Victor Stinner    import threading
1945df820591c319061a625bdd99d7bbd2a26f8117Victor Stinnerexcept ImportError:
2045df820591c319061a625bdd99d7bbd2a26f8117Victor Stinner    threading = None
21292d351fc1a7dc9feccd412843832808680a631fChristian Heimes
22ee8712cda46338d223509cc5751fd36509ad3860Benjamin Petersontest.support.requires("network")
2339f1b3656ed1fdd98d908a21e1b0aafa6b4e75c4Guido van Rossum
24292d351fc1a7dc9feccd412843832808680a631fChristian HeimesTEST_STR = b"hello world\n"
25ee8712cda46338d223509cc5751fd36509ad3860Benjamin PetersonHOST = test.support.HOST
26292d351fc1a7dc9feccd412843832808680a631fChristian Heimes
27292d351fc1a7dc9feccd412843832808680a631fChristian HeimesHAVE_UNIX_SOCKETS = hasattr(socket, "AF_UNIX")
2843767638a9590689fd8bcd1fcedd15bbe4660856Serhiy Storchakarequires_unix_sockets = unittest.skipUnless(HAVE_UNIX_SOCKETS,
2943767638a9590689fd8bcd1fcedd15bbe4660856Serhiy Storchaka                                            'requires Unix sockets')
30f1af7057208da7b3d15703645688fea971a4fb5eJesus CeaHAVE_FORKING = hasattr(os, "fork")
3143767638a9590689fd8bcd1fcedd15bbe4660856Serhiy Storchakarequires_forking = unittest.skipUnless(HAVE_FORKING, 'requires forking')
32292d351fc1a7dc9feccd412843832808680a631fChristian Heimes
33dd15f6c315f20c1a9a540dd757cd63e27dbe9f3cChristian Heimesdef signal_alarm(n):
34dd15f6c315f20c1a9a540dd757cd63e27dbe9f3cChristian Heimes    """Call signal.alarm when it exists (i.e. not on Windows)."""
35dd15f6c315f20c1a9a540dd757cd63e27dbe9f3cChristian Heimes    if hasattr(signal, 'alarm'):
36dd15f6c315f20c1a9a540dd757cd63e27dbe9f3cChristian Heimes        signal.alarm(n)
3739f1b3656ed1fdd98d908a21e1b0aafa6b4e75c4Guido van Rossum
38f18d6f3f443bdfe3f349b2f49231a3c08a5b2d3fAntoine Pitrou# Remember real select() to avoid interferences with mocking
39f18d6f3f443bdfe3f349b2f49231a3c08a5b2d3fAntoine Pitrou_real_select = select.select
40f18d6f3f443bdfe3f349b2f49231a3c08a5b2d3fAntoine Pitrou
41292d351fc1a7dc9feccd412843832808680a631fChristian Heimesdef receive(sock, n, timeout=20):
42f18d6f3f443bdfe3f349b2f49231a3c08a5b2d3fAntoine Pitrou    r, w, x = _real_select([sock], [], [], timeout)
43292d351fc1a7dc9feccd412843832808680a631fChristian Heimes    if sock in r:
44292d351fc1a7dc9feccd412843832808680a631fChristian Heimes        return sock.recv(n)
45292d351fc1a7dc9feccd412843832808680a631fChristian Heimes    else:
46292d351fc1a7dc9feccd412843832808680a631fChristian Heimes        raise RuntimeError("timed out on %r" % (sock,))
47292d351fc1a7dc9feccd412843832808680a631fChristian Heimes
48a945969d717dc8fcb5ca22691f98198b5173b740Gregory P. Smith ext:(%if HAVE_UNIX_SOCKETS and HAVE_FORKING:
49ce261952e640b2d09ada1b160f0cfa37db32f928Alexandre Vassalotti    class ForkingUnixStreamServer(socketserver.ForkingMixIn,
50ce261952e640b2d09ada1b160f0cfa37db32f928Alexandre Vassalotti                                  socketserver.UnixStreamServer):
5115ebc88d87d2ff8f520581a9f6a6816d78a7e504Christian Heimes        pass
5215ebc88d87d2ff8f520581a9f6a6816d78a7e504Christian Heimes
53ce261952e640b2d09ada1b160f0cfa37db32f928Alexandre Vassalotti    class ForkingUnixDatagramServer(socketserver.ForkingMixIn,
54ce261952e640b2d09ada1b160f0cfa37db32f928Alexandre Vassalotti                                    socketserver.UnixDatagramServer):
5515ebc88d87d2ff8f520581a9f6a6816d78a7e504Christian Heimes        pass
56292d351fc1a7dc9feccd412843832808680a631fChristian Heimes
57292d351fc1a7dc9feccd412843832808680a631fChristian Heimes
5870e7ea23f18aacc31f429787645ff8c074c0ad86Christian Heimes@contextlib.contextmanager
5970e7ea23f18aacc31f429787645ff8c074c0ad86Christian Heimesdef simple_subprocess(testcase):
60d9108d1253eef9f43c60e0ed5f1ec5603c1fba6cMartin Panter    """Tests that a custom child process is not waited on (Issue 1540386)"""
6170e7ea23f18aacc31f429787645ff8c074c0ad86Christian Heimes    pid = os.fork()
6270e7ea23f18aacc31f429787645ff8c074c0ad86Christian Heimes    if pid == 0:
63737fb89dd15e4db6ef30d25963e774ae09cc49dcAndrew Svetlov        # Don't raise an exception; it would be caught by the test harness.
6470e7ea23f18aacc31f429787645ff8c074c0ad86Christian Heimes        os._exit(72)
6570e7ea23f18aacc31f429787645ff8c074c0ad86Christian Heimes    yield None
6670e7ea23f18aacc31f429787645ff8c074c0ad86Christian Heimes    pid2, status = os.waitpid(pid, 0)
67b3aedd48621ed9d33b5f42f946b256bce4a50673Ezio Melotti    testcase.assertEqual(pid2, pid)
68b3aedd48621ed9d33b5f42f946b256bce4a50673Ezio Melotti    testcase.assertEqual(72 << 8, status)
6970e7ea23f18aacc31f429787645ff8c074c0ad86Christian Heimes
7070e7ea23f18aacc31f429787645ff8c074c0ad86Christian Heimes
715f22e72e6dc5e4fdebd6cd41a7f9692f986ce9d4Victor Stinner@unittest.skipUnless(threading, 'Threading required for this test.')
72292d351fc1a7dc9feccd412843832808680a631fChristian Heimesclass SocketServerTest(unittest.TestCase):
73292d351fc1a7dc9feccd412843832808680a631fChristian Heimes    """Test all socket servers."""
74292d351fc1a7dc9feccd412843832808680a631fChristian Heimes
75292d351fc1a7dc9feccd412843832808680a631fChristian Heimes    def setUp(self):
765702ae6f3f3884339be54f92ce26503373543caeVictor Stinner        signal_alarm(60)  # Kill deadlocks after 60 seconds.
77292d351fc1a7dc9feccd412843832808680a631fChristian Heimes        self.port_seed = 0
78292d351fc1a7dc9feccd412843832808680a631fChristian Heimes        self.test_files = []
79292d351fc1a7dc9feccd412843832808680a631fChristian Heimes
80292d351fc1a7dc9feccd412843832808680a631fChristian Heimes    def tearDown(self):
81fe337bfd0d89c62917e3625111c65f4aa187c6b4Christian Heimes        signal_alarm(0)  # Didn't deadlock.
82292d351fc1a7dc9feccd412843832808680a631fChristian Heimes        reap_children()
83292d351fc1a7dc9feccd412843832808680a631fChristian Heimes
84292d351fc1a7dc9feccd412843832808680a631fChristian Heimes        for fn in self.test_files:
85292d351fc1a7dc9feccd412843832808680a631fChristian Heimes            try:
86292d351fc1a7dc9feccd412843832808680a631fChristian Heimes                os.remove(fn)
87ad28c7f9dad791567afa0624acfb3ba430851965Andrew Svetlov            except OSError:
88292d351fc1a7dc9feccd412843832808680a631fChristian Heimes                pass
89292d351fc1a7dc9feccd412843832808680a631fChristian Heimes        self.test_files[:] = []
90292d351fc1a7dc9feccd412843832808680a631fChristian Heimes
91292d351fc1a7dc9feccd412843832808680a631fChristian Heimes    def pickaddr(self, proto):
92292d351fc1a7dc9feccd412843832808680a631fChristian Heimes        if proto == socket.AF_INET:
939e7f1d2e965400edcb2c0cb7fee625ef2b595eb5Christian Heimes            return (HOST, 0)
94292d351fc1a7dc9feccd412843832808680a631fChristian Heimes        else:
959e7f1d2e965400edcb2c0cb7fee625ef2b595eb5Christian Heimes            # XXX: We need a way to tell AF_UNIX to pick its own name
969e7f1d2e965400edcb2c0cb7fee625ef2b595eb5Christian Heimes            # like AF_INET provides port==0.
979e7f1d2e965400edcb2c0cb7fee625ef2b595eb5Christian Heimes            dir = None
989e7f1d2e965400edcb2c0cb7fee625ef2b595eb5Christian Heimes            fn = tempfile.mktemp(prefix='unix_socket.', dir=dir)
99292d351fc1a7dc9feccd412843832808680a631fChristian Heimes            self.test_files.append(fn)
100292d351fc1a7dc9feccd412843832808680a631fChristian Heimes            return fn
101292d351fc1a7dc9feccd412843832808680a631fChristian Heimes
102dd15f6c315f20c1a9a540dd757cd63e27dbe9f3cChristian Heimes    def make_server(self, addr, svrcls, hdlrbase):
103dd15f6c315f20c1a9a540dd757cd63e27dbe9f3cChristian Heimes        class MyServer(svrcls):
104dd15f6c315f20c1a9a540dd757cd63e27dbe9f3cChristian Heimes            def handle_error(self, request, client_address):
105dd15f6c315f20c1a9a540dd757cd63e27dbe9f3cChristian Heimes                self.close_request(request)
106dd15f6c315f20c1a9a540dd757cd63e27dbe9f3cChristian Heimes                raise
1079e7f1d2e965400edcb2c0cb7fee625ef2b595eb5Christian Heimes
1089e7f1d2e965400edcb2c0cb7fee625ef2b595eb5Christian Heimes        class MyHandler(hdlrbase):
1099e7f1d2e965400edcb2c0cb7fee625ef2b595eb5Christian Heimes            def handle(self):
1109e7f1d2e965400edcb2c0cb7fee625ef2b595eb5Christian Heimes                line = self.rfile.readline()
1119e7f1d2e965400edcb2c0cb7fee625ef2b595eb5Christian Heimes                self.wfile.write(line)
1129e7f1d2e965400edcb2c0cb7fee625ef2b595eb5Christian Heimes
113dd15f6c315f20c1a9a540dd757cd63e27dbe9f3cChristian Heimes        if verbose: print("creating server")
114dd15f6c315f20c1a9a540dd757cd63e27dbe9f3cChristian Heimes        server = MyServer(addr, MyHandler)
115b3aedd48621ed9d33b5f42f946b256bce4a50673Ezio Melotti        self.assertEqual(server.server_address, server.socket.getsockname())
116dd15f6c315f20c1a9a540dd757cd63e27dbe9f3cChristian Heimes        return server
117dd15f6c315f20c1a9a540dd757cd63e27dbe9f3cChristian Heimes
118c00d4b437d544268b699fc57fe9e7c57ae89f1b3Antoine Pitrou    @reap_threads
119dd15f6c315f20c1a9a540dd757cd63e27dbe9f3cChristian Heimes    def run_server(self, svrcls, hdlrbase, testfunc):
120dd15f6c315f20c1a9a540dd757cd63e27dbe9f3cChristian Heimes        server = self.make_server(self.pickaddr(svrcls.address_family),
121dd15f6c315f20c1a9a540dd757cd63e27dbe9f3cChristian Heimes                                  svrcls, hdlrbase)
122dd15f6c315f20c1a9a540dd757cd63e27dbe9f3cChristian Heimes        # We had the OS pick a port, so pull the real address out of
123dd15f6c315f20c1a9a540dd757cd63e27dbe9f3cChristian Heimes        # the server.
124dd15f6c315f20c1a9a540dd757cd63e27dbe9f3cChristian Heimes        addr = server.server_address
1259e7f1d2e965400edcb2c0cb7fee625ef2b595eb5Christian Heimes        if verbose:
1269e7f1d2e965400edcb2c0cb7fee625ef2b595eb5Christian Heimes            print("ADDR =", addr)
1279e7f1d2e965400edcb2c0cb7fee625ef2b595eb5Christian Heimes            print("CLASS =", svrcls)
128dd15f6c315f20c1a9a540dd757cd63e27dbe9f3cChristian Heimes
129dd15f6c315f20c1a9a540dd757cd63e27dbe9f3cChristian Heimes        t = threading.Thread(
130dd15f6c315f20c1a9a540dd757cd63e27dbe9f3cChristian Heimes            name='%s serving' % svrcls,
131dd15f6c315f20c1a9a540dd757cd63e27dbe9f3cChristian Heimes            target=server.serve_forever,
132dd15f6c315f20c1a9a540dd757cd63e27dbe9f3cChristian Heimes            # Short poll interval to make the test finish quickly.
133dd15f6c315f20c1a9a540dd757cd63e27dbe9f3cChristian Heimes            # Time between requests is short enough that we won't wake
134dd15f6c315f20c1a9a540dd757cd63e27dbe9f3cChristian Heimes            # up spuriously too many times.
135dd15f6c315f20c1a9a540dd757cd63e27dbe9f3cChristian Heimes            kwargs={'poll_interval':0.01})
136727537077043bb03a0c9e537cacbb9e695f7f4a8Benjamin Peterson        t.daemon = True  # In case this function raises.
1379e7f1d2e965400edcb2c0cb7fee625ef2b595eb5Christian Heimes        t.start()
1389e7f1d2e965400edcb2c0cb7fee625ef2b595eb5Christian Heimes        if verbose: print("server running")
139dd15f6c315f20c1a9a540dd757cd63e27dbe9f3cChristian Heimes        for i in range(3):
1409e7f1d2e965400edcb2c0cb7fee625ef2b595eb5Christian Heimes            if verbose: print("test client", i)
1419e7f1d2e965400edcb2c0cb7fee625ef2b595eb5Christian Heimes            testfunc(svrcls.address_family, addr)
1429e7f1d2e965400edcb2c0cb7fee625ef2b595eb5Christian Heimes        if verbose: print("waiting for server")
143dd15f6c315f20c1a9a540dd757cd63e27dbe9f3cChristian Heimes        server.shutdown()
1449e7f1d2e965400edcb2c0cb7fee625ef2b595eb5Christian Heimes        t.join()
145109761ba076842a9ab4343f083d46658829067b9Victor Stinner        server.server_close()
1461ee9283254446998c9f423896b1edffe42f246d3Robert Collins        self.assertEqual(-1, server.socket.fileno())
1479e7f1d2e965400edcb2c0cb7fee625ef2b595eb5Christian Heimes        if verbose: print("done")
148292d351fc1a7dc9feccd412843832808680a631fChristian Heimes
149292d351fc1a7dc9feccd412843832808680a631fChristian Heimes    def stream_examine(self, proto, addr):
150292d351fc1a7dc9feccd412843832808680a631fChristian Heimes        s = socket.socket(proto, socket.SOCK_STREAM)
151292d351fc1a7dc9feccd412843832808680a631fChristian Heimes        s.connect(addr)
152292d351fc1a7dc9feccd412843832808680a631fChristian Heimes        s.sendall(TEST_STR)
153292d351fc1a7dc9feccd412843832808680a631fChristian Heimes        buf = data = receive(s, 100)
154fdb6bb56c19c6c0d332d61fb3f6416cf91be2d02Christian Heimes        while data and b'\n' not in buf:
155292d351fc1a7dc9feccd412843832808680a631fChristian Heimes            data = receive(s, 100)
156292d351fc1a7dc9feccd412843832808680a631fChristian Heimes            buf += data
157b3aedd48621ed9d33b5f42f946b256bce4a50673Ezio Melotti        self.assertEqual(buf, TEST_STR)
158292d351fc1a7dc9feccd412843832808680a631fChristian Heimes        s.close()
159292d351fc1a7dc9feccd412843832808680a631fChristian Heimes
160292d351fc1a7dc9feccd412843832808680a631fChristian Heimes    def dgram_examine(self, proto, addr):
161292d351fc1a7dc9feccd412843832808680a631fChristian Heimes        s = socket.socket(proto, socket.SOCK_DGRAM)
1621827eff03087d0e7975806967a68a349e10e5188Martin Panter        if HAVE_UNIX_SOCKETS and proto == socket.AF_UNIX:
1631827eff03087d0e7975806967a68a349e10e5188Martin Panter            s.bind(self.pickaddr(proto))
164292d351fc1a7dc9feccd412843832808680a631fChristian Heimes        s.sendto(TEST_STR, addr)
165292d351fc1a7dc9feccd412843832808680a631fChristian Heimes        buf = data = receive(s, 100)
166fdb6bb56c19c6c0d332d61fb3f6416cf91be2d02Christian Heimes        while data and b'\n' not in buf:
167292d351fc1a7dc9feccd412843832808680a631fChristian Heimes            data = receive(s, 100)
168292d351fc1a7dc9feccd412843832808680a631fChristian Heimes            buf += data
169b3aedd48621ed9d33b5f42f946b256bce4a50673Ezio Melotti        self.assertEqual(buf, TEST_STR)
170292d351fc1a7dc9feccd412843832808680a631fChristian Heimes        s.close()
171292d351fc1a7dc9feccd412843832808680a631fChristian Heimes
1729e7f1d2e965400edcb2c0cb7fee625ef2b595eb5Christian Heimes    def test_TCPServer(self):
173ce261952e640b2d09ada1b160f0cfa37db32f928Alexandre Vassalotti        self.run_server(socketserver.TCPServer,
174ce261952e640b2d09ada1b160f0cfa37db32f928Alexandre Vassalotti                        socketserver.StreamRequestHandler,
1759e7f1d2e965400edcb2c0cb7fee625ef2b595eb5Christian Heimes                        self.stream_examine)
1769e7f1d2e965400edcb2c0cb7fee625ef2b595eb5Christian Heimes
1779e7f1d2e965400edcb2c0cb7fee625ef2b595eb5Christian Heimes    def test_ThreadingTCPServer(self):
178ce261952e640b2d09ada1b160f0cfa37db32f928Alexandre Vassalotti        self.run_server(socketserver.ThreadingTCPServer,
179ce261952e640b2d09ada1b160f0cfa37db32f928Alexandre Vassalotti                        socketserver.StreamRequestHandler,
1809e7f1d2e965400edcb2c0cb7fee625ef2b595eb5Christian Heimes                        self.stream_examine)
1819e7f1d2e965400edcb2c0cb7fee625ef2b595eb5Christian Heimes
18243767638a9590689fd8bcd1fcedd15bbe4660856Serhiy Storchaka    @requires_forking
18343767638a9590689fd8bcd1fcedd15bbe4660856Serhiy Storchaka    def test_ForkingTCPServer(self):
18443767638a9590689fd8bcd1fcedd15bbe4660856Serhiy Storchaka        with simple_subprocess(self):
18543767638a9590689fd8bcd1fcedd15bbe4660856Serhiy Storchaka            self.run_server(socketserver.ForkingTCPServer,
186ce261952e640b2d09ada1b160f0cfa37db32f928Alexandre Vassalotti                            socketserver.StreamRequestHandler,
1879e7f1d2e965400edcb2c0cb7fee625ef2b595eb5Christian Heimes                            self.stream_examine)
1889e7f1d2e965400edcb2c0cb7fee625ef2b595eb5Christian Heimes
18943767638a9590689fd8bcd1fcedd15bbe4660856Serhiy Storchaka    @requires_unix_sockets
19043767638a9590689fd8bcd1fcedd15bbe4660856Serhiy Storchaka    def test_UnixStreamServer(self):
19143767638a9590689fd8bcd1fcedd15bbe4660856Serhiy Storchaka        self.run_server(socketserver.UnixStreamServer,
19243767638a9590689fd8bcd1fcedd15bbe4660856Serhiy Storchaka                        socketserver.StreamRequestHandler,
19343767638a9590689fd8bcd1fcedd15bbe4660856Serhiy Storchaka                        self.stream_examine)
19443767638a9590689fd8bcd1fcedd15bbe4660856Serhiy Storchaka
19543767638a9590689fd8bcd1fcedd15bbe4660856Serhiy Storchaka    @requires_unix_sockets
19643767638a9590689fd8bcd1fcedd15bbe4660856Serhiy Storchaka    def test_ThreadingUnixStreamServer(self):
19743767638a9590689fd8bcd1fcedd15bbe4660856Serhiy Storchaka        self.run_server(socketserver.ThreadingUnixStreamServer,
19843767638a9590689fd8bcd1fcedd15bbe4660856Serhiy Storchaka                        socketserver.StreamRequestHandler,
19943767638a9590689fd8bcd1fcedd15bbe4660856Serhiy Storchaka                        self.stream_examine)
20043767638a9590689fd8bcd1fcedd15bbe4660856Serhiy Storchaka
20143767638a9590689fd8bcd1fcedd15bbe4660856Serhiy Storchaka    @requires_unix_sockets
20243767638a9590689fd8bcd1fcedd15bbe4660856Serhiy Storchaka    @requires_forking
20343767638a9590689fd8bcd1fcedd15bbe4660856Serhiy Storchaka    def test_ForkingUnixStreamServer(self):
20443767638a9590689fd8bcd1fcedd15bbe4660856Serhiy Storchaka        with simple_subprocess(self):
20543767638a9590689fd8bcd1fcedd15bbe4660856Serhiy Storchaka            self.run_server(ForkingUnixStreamServer,
206ce261952e640b2d09ada1b160f0cfa37db32f928Alexandre Vassalotti                            socketserver.StreamRequestHandler,
2079e7f1d2e965400edcb2c0cb7fee625ef2b595eb5Christian Heimes                            self.stream_examine)
2089e7f1d2e965400edcb2c0cb7fee625ef2b595eb5Christian Heimes
2099e7f1d2e965400edcb2c0cb7fee625ef2b595eb5Christian Heimes    def test_UDPServer(self):
210ce261952e640b2d09ada1b160f0cfa37db32f928Alexandre Vassalotti        self.run_server(socketserver.UDPServer,
211ce261952e640b2d09ada1b160f0cfa37db32f928Alexandre Vassalotti                        socketserver.DatagramRequestHandler,
2129e7f1d2e965400edcb2c0cb7fee625ef2b595eb5Christian Heimes                        self.dgram_examine)
2139e7f1d2e965400edcb2c0cb7fee625ef2b595eb5Christian Heimes
2149e7f1d2e965400edcb2c0cb7fee625ef2b595eb5Christian Heimes    def test_ThreadingUDPServer(self):
215ce261952e640b2d09ada1b160f0cfa37db32f928Alexandre Vassalotti        self.run_server(socketserver.ThreadingUDPServer,
216ce261952e640b2d09ada1b160f0cfa37db32f928Alexandre Vassalotti                        socketserver.DatagramRequestHandler,
2179e7f1d2e965400edcb2c0cb7fee625ef2b595eb5Christian Heimes                        self.dgram_examine)
2189e7f1d2e965400edcb2c0cb7fee625ef2b595eb5Christian Heimes
21943767638a9590689fd8bcd1fcedd15bbe4660856Serhiy Storchaka    @requires_forking
22043767638a9590689fd8bcd1fcedd15bbe4660856Serhiy Storchaka    def test_ForkingUDPServer(self):
22143767638a9590689fd8bcd1fcedd15bbe4660856Serhiy Storchaka        with simple_subprocess(self):
22243767638a9590689fd8bcd1fcedd15bbe4660856Serhiy Storchaka            self.run_server(socketserver.ForkingUDPServer,
22343767638a9590689fd8bcd1fcedd15bbe4660856Serhiy Storchaka                            socketserver.DatagramRequestHandler,
22443767638a9590689fd8bcd1fcedd15bbe4660856Serhiy Storchaka                            self.dgram_examine)
225292d351fc1a7dc9feccd412843832808680a631fChristian Heimes
2261827eff03087d0e7975806967a68a349e10e5188Martin Panter    @requires_unix_sockets
2271827eff03087d0e7975806967a68a349e10e5188Martin Panter    def test_UnixDatagramServer(self):
2281827eff03087d0e7975806967a68a349e10e5188Martin Panter        self.run_server(socketserver.UnixDatagramServer,
2291827eff03087d0e7975806967a68a349e10e5188Martin Panter                        socketserver.DatagramRequestHandler,
2301827eff03087d0e7975806967a68a349e10e5188Martin Panter                        self.dgram_examine)
2311827eff03087d0e7975806967a68a349e10e5188Martin Panter
2321827eff03087d0e7975806967a68a349e10e5188Martin Panter    @requires_unix_sockets
2331827eff03087d0e7975806967a68a349e10e5188Martin Panter    def test_ThreadingUnixDatagramServer(self):
2341827eff03087d0e7975806967a68a349e10e5188Martin Panter        self.run_server(socketserver.ThreadingUnixDatagramServer,
2351827eff03087d0e7975806967a68a349e10e5188Martin Panter                        socketserver.DatagramRequestHandler,
2361827eff03087d0e7975806967a68a349e10e5188Martin Panter                        self.dgram_examine)
2371827eff03087d0e7975806967a68a349e10e5188Martin Panter
2381827eff03087d0e7975806967a68a349e10e5188Martin Panter    @requires_unix_sockets
2391827eff03087d0e7975806967a68a349e10e5188Martin Panter    @requires_forking
2401827eff03087d0e7975806967a68a349e10e5188Martin Panter    def test_ForkingUnixDatagramServer(self):
2411827eff03087d0e7975806967a68a349e10e5188Martin Panter        self.run_server(ForkingUnixDatagramServer,
2421827eff03087d0e7975806967a68a349e10e5188Martin Panter                        socketserver.DatagramRequestHandler,
2431827eff03087d0e7975806967a68a349e10e5188Martin Panter                        self.dgram_examine)
244292d351fc1a7dc9feccd412843832808680a631fChristian Heimes
2453bcba8e2889708f646df50953cd45a4f2cf28b02Antoine Pitrou    @reap_threads
2463bcba8e2889708f646df50953cd45a4f2cf28b02Antoine Pitrou    def test_shutdown(self):
2473bcba8e2889708f646df50953cd45a4f2cf28b02Antoine Pitrou        # Issue #2302: shutdown() should always succeed in making an
2483bcba8e2889708f646df50953cd45a4f2cf28b02Antoine Pitrou        # other thread leave serve_forever().
2493bcba8e2889708f646df50953cd45a4f2cf28b02Antoine Pitrou        class MyServer(socketserver.TCPServer):
2503bcba8e2889708f646df50953cd45a4f2cf28b02Antoine Pitrou            pass
2513bcba8e2889708f646df50953cd45a4f2cf28b02Antoine Pitrou
2523bcba8e2889708f646df50953cd45a4f2cf28b02Antoine Pitrou        class MyHandler(socketserver.StreamRequestHandler):
2533bcba8e2889708f646df50953cd45a4f2cf28b02Antoine Pitrou            pass
2543bcba8e2889708f646df50953cd45a4f2cf28b02Antoine Pitrou
2553bcba8e2889708f646df50953cd45a4f2cf28b02Antoine Pitrou        threads = []
2563bcba8e2889708f646df50953cd45a4f2cf28b02Antoine Pitrou        for i in range(20):
2573bcba8e2889708f646df50953cd45a4f2cf28b02Antoine Pitrou            s = MyServer((HOST, 0), MyHandler)
2583bcba8e2889708f646df50953cd45a4f2cf28b02Antoine Pitrou            t = threading.Thread(
2593bcba8e2889708f646df50953cd45a4f2cf28b02Antoine Pitrou                name='MyServer serving',
2603bcba8e2889708f646df50953cd45a4f2cf28b02Antoine Pitrou                target=s.serve_forever,
2613bcba8e2889708f646df50953cd45a4f2cf28b02Antoine Pitrou                kwargs={'poll_interval':0.01})
2623bcba8e2889708f646df50953cd45a4f2cf28b02Antoine Pitrou            t.daemon = True  # In case this function raises.
2633bcba8e2889708f646df50953cd45a4f2cf28b02Antoine Pitrou            threads.append((t, s))
2643bcba8e2889708f646df50953cd45a4f2cf28b02Antoine Pitrou        for t, s in threads:
2653bcba8e2889708f646df50953cd45a4f2cf28b02Antoine Pitrou            t.start()
2663bcba8e2889708f646df50953cd45a4f2cf28b02Antoine Pitrou            s.shutdown()
2673bcba8e2889708f646df50953cd45a4f2cf28b02Antoine Pitrou        for t, s in threads:
2683bcba8e2889708f646df50953cd45a4f2cf28b02Antoine Pitrou            t.join()
269109761ba076842a9ab4343f083d46658829067b9Victor Stinner            s.server_close()
2703bcba8e2889708f646df50953cd45a4f2cf28b02Antoine Pitrou
2710f4f048fa5ff06438a4624bc1dc02aa458a79748Charles-François Natali    def test_tcpserver_bind_leak(self):
2720f4f048fa5ff06438a4624bc1dc02aa458a79748Charles-François Natali        # Issue #22435: the server socket wouldn't be closed if bind()/listen()
2730f4f048fa5ff06438a4624bc1dc02aa458a79748Charles-François Natali        # failed.
2740f4f048fa5ff06438a4624bc1dc02aa458a79748Charles-François Natali        # Create many servers for which bind() will fail, to see if this result
2750f4f048fa5ff06438a4624bc1dc02aa458a79748Charles-François Natali        # in FD exhaustion.
2760f4f048fa5ff06438a4624bc1dc02aa458a79748Charles-François Natali        for i in range(1024):
2770f4f048fa5ff06438a4624bc1dc02aa458a79748Charles-François Natali            with self.assertRaises(OverflowError):
2780f4f048fa5ff06438a4624bc1dc02aa458a79748Charles-François Natali                socketserver.TCPServer((HOST, -1),
2790f4f048fa5ff06438a4624bc1dc02aa458a79748Charles-François Natali                                       socketserver.StreamRequestHandler)
2800f4f048fa5ff06438a4624bc1dc02aa458a79748Charles-François Natali
2810cab9c1ebaa11bb7838a552c671c903156262ab7Martin Panter    def test_context_manager(self):
2820cab9c1ebaa11bb7838a552c671c903156262ab7Martin Panter        with socketserver.TCPServer((HOST, 0),
2830cab9c1ebaa11bb7838a552c671c903156262ab7Martin Panter                                    socketserver.StreamRequestHandler) as server:
2840cab9c1ebaa11bb7838a552c671c903156262ab7Martin Panter            pass
2850cab9c1ebaa11bb7838a552c671c903156262ab7Martin Panter        self.assertEqual(-1, server.socket.fileno())
2860cab9c1ebaa11bb7838a552c671c903156262ab7Martin Panter
28739f1b3656ed1fdd98d908a21e1b0aafa6b4e75c4Guido van Rossum
288d9108d1253eef9f43c60e0ed5f1ec5603c1fba6cMartin Panterclass ErrorHandlerTest(unittest.TestCase):
289d9108d1253eef9f43c60e0ed5f1ec5603c1fba6cMartin Panter    """Test that the servers pass normal exceptions from the handler to
290d9108d1253eef9f43c60e0ed5f1ec5603c1fba6cMartin Panter    handle_error(), and that exiting exceptions like SystemExit and
291d9108d1253eef9f43c60e0ed5f1ec5603c1fba6cMartin Panter    KeyboardInterrupt are not passed."""
292d9108d1253eef9f43c60e0ed5f1ec5603c1fba6cMartin Panter
293d9108d1253eef9f43c60e0ed5f1ec5603c1fba6cMartin Panter    def tearDown(self):
294d9108d1253eef9f43c60e0ed5f1ec5603c1fba6cMartin Panter        test.support.unlink(test.support.TESTFN)
295d9108d1253eef9f43c60e0ed5f1ec5603c1fba6cMartin Panter
296d9108d1253eef9f43c60e0ed5f1ec5603c1fba6cMartin Panter    def test_sync_handled(self):
297d9108d1253eef9f43c60e0ed5f1ec5603c1fba6cMartin Panter        BaseErrorTestServer(ValueError)
298d9108d1253eef9f43c60e0ed5f1ec5603c1fba6cMartin Panter        self.check_result(handled=True)
299d9108d1253eef9f43c60e0ed5f1ec5603c1fba6cMartin Panter
300d9108d1253eef9f43c60e0ed5f1ec5603c1fba6cMartin Panter    def test_sync_not_handled(self):
301d9108d1253eef9f43c60e0ed5f1ec5603c1fba6cMartin Panter        with self.assertRaises(SystemExit):
302d9108d1253eef9f43c60e0ed5f1ec5603c1fba6cMartin Panter            BaseErrorTestServer(SystemExit)
303d9108d1253eef9f43c60e0ed5f1ec5603c1fba6cMartin Panter        self.check_result(handled=False)
304d9108d1253eef9f43c60e0ed5f1ec5603c1fba6cMartin Panter
305d9108d1253eef9f43c60e0ed5f1ec5603c1fba6cMartin Panter    @unittest.skipUnless(threading, 'Threading required for this test.')
306d9108d1253eef9f43c60e0ed5f1ec5603c1fba6cMartin Panter    def test_threading_handled(self):
307d9108d1253eef9f43c60e0ed5f1ec5603c1fba6cMartin Panter        ThreadingErrorTestServer(ValueError)
308d9108d1253eef9f43c60e0ed5f1ec5603c1fba6cMartin Panter        self.check_result(handled=True)
309d9108d1253eef9f43c60e0ed5f1ec5603c1fba6cMartin Panter
310d9108d1253eef9f43c60e0ed5f1ec5603c1fba6cMartin Panter    @unittest.skipUnless(threading, 'Threading required for this test.')
311d9108d1253eef9f43c60e0ed5f1ec5603c1fba6cMartin Panter    def test_threading_not_handled(self):
312d9108d1253eef9f43c60e0ed5f1ec5603c1fba6cMartin Panter        ThreadingErrorTestServer(SystemExit)
313d9108d1253eef9f43c60e0ed5f1ec5603c1fba6cMartin Panter        self.check_result(handled=False)
314d9108d1253eef9f43c60e0ed5f1ec5603c1fba6cMartin Panter
315d9108d1253eef9f43c60e0ed5f1ec5603c1fba6cMartin Panter    @requires_forking
316d9108d1253eef9f43c60e0ed5f1ec5603c1fba6cMartin Panter    def test_forking_handled(self):
317d9108d1253eef9f43c60e0ed5f1ec5603c1fba6cMartin Panter        ForkingErrorTestServer(ValueError)
318d9108d1253eef9f43c60e0ed5f1ec5603c1fba6cMartin Panter        self.check_result(handled=True)
319d9108d1253eef9f43c60e0ed5f1ec5603c1fba6cMartin Panter
320d9108d1253eef9f43c60e0ed5f1ec5603c1fba6cMartin Panter    @requires_forking
321d9108d1253eef9f43c60e0ed5f1ec5603c1fba6cMartin Panter    def test_forking_not_handled(self):
322d9108d1253eef9f43c60e0ed5f1ec5603c1fba6cMartin Panter        ForkingErrorTestServer(SystemExit)
323d9108d1253eef9f43c60e0ed5f1ec5603c1fba6cMartin Panter        self.check_result(handled=False)
324d9108d1253eef9f43c60e0ed5f1ec5603c1fba6cMartin Panter
325d9108d1253eef9f43c60e0ed5f1ec5603c1fba6cMartin Panter    def check_result(self, handled):
326d9108d1253eef9f43c60e0ed5f1ec5603c1fba6cMartin Panter        with open(test.support.TESTFN) as log:
327d9108d1253eef9f43c60e0ed5f1ec5603c1fba6cMartin Panter            expected = 'Handler called\n' + 'Error handled\n' * handled
328d9108d1253eef9f43c60e0ed5f1ec5603c1fba6cMartin Panter            self.assertEqual(log.read(), expected)
329d9108d1253eef9f43c60e0ed5f1ec5603c1fba6cMartin Panter
330d9108d1253eef9f43c60e0ed5f1ec5603c1fba6cMartin Panter
331d9108d1253eef9f43c60e0ed5f1ec5603c1fba6cMartin Panterclass BaseErrorTestServer(socketserver.TCPServer):
332d9108d1253eef9f43c60e0ed5f1ec5603c1fba6cMartin Panter    def __init__(self, exception):
333d9108d1253eef9f43c60e0ed5f1ec5603c1fba6cMartin Panter        self.exception = exception
334d9108d1253eef9f43c60e0ed5f1ec5603c1fba6cMartin Panter        super().__init__((HOST, 0), BadHandler)
335d9108d1253eef9f43c60e0ed5f1ec5603c1fba6cMartin Panter        with socket.create_connection(self.server_address):
336d9108d1253eef9f43c60e0ed5f1ec5603c1fba6cMartin Panter            pass
337d9108d1253eef9f43c60e0ed5f1ec5603c1fba6cMartin Panter        try:
338d9108d1253eef9f43c60e0ed5f1ec5603c1fba6cMartin Panter            self.handle_request()
339d9108d1253eef9f43c60e0ed5f1ec5603c1fba6cMartin Panter        finally:
340d9108d1253eef9f43c60e0ed5f1ec5603c1fba6cMartin Panter            self.server_close()
341d9108d1253eef9f43c60e0ed5f1ec5603c1fba6cMartin Panter        self.wait_done()
342d9108d1253eef9f43c60e0ed5f1ec5603c1fba6cMartin Panter
343d9108d1253eef9f43c60e0ed5f1ec5603c1fba6cMartin Panter    def handle_error(self, request, client_address):
344d9108d1253eef9f43c60e0ed5f1ec5603c1fba6cMartin Panter        with open(test.support.TESTFN, 'a') as log:
345d9108d1253eef9f43c60e0ed5f1ec5603c1fba6cMartin Panter            log.write('Error handled\n')
346d9108d1253eef9f43c60e0ed5f1ec5603c1fba6cMartin Panter
347d9108d1253eef9f43c60e0ed5f1ec5603c1fba6cMartin Panter    def wait_done(self):
348d9108d1253eef9f43c60e0ed5f1ec5603c1fba6cMartin Panter        pass
349d9108d1253eef9f43c60e0ed5f1ec5603c1fba6cMartin Panter
350d9108d1253eef9f43c60e0ed5f1ec5603c1fba6cMartin Panter
351d9108d1253eef9f43c60e0ed5f1ec5603c1fba6cMartin Panterclass BadHandler(socketserver.BaseRequestHandler):
352d9108d1253eef9f43c60e0ed5f1ec5603c1fba6cMartin Panter    def handle(self):
353d9108d1253eef9f43c60e0ed5f1ec5603c1fba6cMartin Panter        with open(test.support.TESTFN, 'a') as log:
354d9108d1253eef9f43c60e0ed5f1ec5603c1fba6cMartin Panter            log.write('Handler called\n')
355d9108d1253eef9f43c60e0ed5f1ec5603c1fba6cMartin Panter        raise self.server.exception('Test error')
356d9108d1253eef9f43c60e0ed5f1ec5603c1fba6cMartin Panter
357d9108d1253eef9f43c60e0ed5f1ec5603c1fba6cMartin Panter
358d9108d1253eef9f43c60e0ed5f1ec5603c1fba6cMartin Panterclass ThreadingErrorTestServer(socketserver.ThreadingMixIn,
359d9108d1253eef9f43c60e0ed5f1ec5603c1fba6cMartin Panter        BaseErrorTestServer):
360d9108d1253eef9f43c60e0ed5f1ec5603c1fba6cMartin Panter    def __init__(self, *pos, **kw):
361d9108d1253eef9f43c60e0ed5f1ec5603c1fba6cMartin Panter        self.done = threading.Event()
362d9108d1253eef9f43c60e0ed5f1ec5603c1fba6cMartin Panter        super().__init__(*pos, **kw)
363d9108d1253eef9f43c60e0ed5f1ec5603c1fba6cMartin Panter
364d9108d1253eef9f43c60e0ed5f1ec5603c1fba6cMartin Panter    def shutdown_request(self, *pos, **kw):
365d9108d1253eef9f43c60e0ed5f1ec5603c1fba6cMartin Panter        super().shutdown_request(*pos, **kw)
366d9108d1253eef9f43c60e0ed5f1ec5603c1fba6cMartin Panter        self.done.set()
367d9108d1253eef9f43c60e0ed5f1ec5603c1fba6cMartin Panter
368d9108d1253eef9f43c60e0ed5f1ec5603c1fba6cMartin Panter    def wait_done(self):
369d9108d1253eef9f43c60e0ed5f1ec5603c1fba6cMartin Panter        self.done.wait()
370d9108d1253eef9f43c60e0ed5f1ec5603c1fba6cMartin Panter
371d9108d1253eef9f43c60e0ed5f1ec5603c1fba6cMartin Panter
372a945969d717dc8fcb5ca22691f98198b5173b740Gregory P. Smith ext:(%if HAVE_FORKING:
373a945969d717dc8fcb5ca22691f98198b5173b740Gregory P. Smith ext:(%    class ForkingErrorTestServer(socketserver.ForkingMixIn, BaseErrorTestServer):
374a945969d717dc8fcb5ca22691f98198b5173b740Gregory P. Smith ext:(%        def wait_done(self):
375a945969d717dc8fcb5ca22691f98198b5173b740Gregory P. Smith ext:(%            [child] = self.active_children
376a945969d717dc8fcb5ca22691f98198b5173b740Gregory P. Smith ext:(%            os.waitpid(child, 0)
377a945969d717dc8fcb5ca22691f98198b5173b740Gregory P. Smith ext:(%            self.active_children.clear()
378d9108d1253eef9f43c60e0ed5f1ec5603c1fba6cMartin Panter
379d9108d1253eef9f43c60e0ed5f1ec5603c1fba6cMartin Panter
38034eeed42901666fce099947f93dfdfc05411f286Martin Panterclass SocketWriterTest(unittest.TestCase):
38134eeed42901666fce099947f93dfdfc05411f286Martin Panter    def test_basics(self):
38234eeed42901666fce099947f93dfdfc05411f286Martin Panter        class Handler(socketserver.StreamRequestHandler):
38334eeed42901666fce099947f93dfdfc05411f286Martin Panter            def handle(self):
38434eeed42901666fce099947f93dfdfc05411f286Martin Panter                self.server.wfile = self.wfile
38534eeed42901666fce099947f93dfdfc05411f286Martin Panter                self.server.wfile_fileno = self.wfile.fileno()
38634eeed42901666fce099947f93dfdfc05411f286Martin Panter                self.server.request_fileno = self.request.fileno()
38734eeed42901666fce099947f93dfdfc05411f286Martin Panter
38834eeed42901666fce099947f93dfdfc05411f286Martin Panter        server = socketserver.TCPServer((HOST, 0), Handler)
38934eeed42901666fce099947f93dfdfc05411f286Martin Panter        self.addCleanup(server.server_close)
39034eeed42901666fce099947f93dfdfc05411f286Martin Panter        s = socket.socket(
39134eeed42901666fce099947f93dfdfc05411f286Martin Panter            server.address_family, socket.SOCK_STREAM, socket.IPPROTO_TCP)
39234eeed42901666fce099947f93dfdfc05411f286Martin Panter        with s:
39334eeed42901666fce099947f93dfdfc05411f286Martin Panter            s.connect(server.server_address)
39434eeed42901666fce099947f93dfdfc05411f286Martin Panter        server.handle_request()
39534eeed42901666fce099947f93dfdfc05411f286Martin Panter        self.assertIsInstance(server.wfile, io.BufferedIOBase)
39634eeed42901666fce099947f93dfdfc05411f286Martin Panter        self.assertEqual(server.wfile_fileno, server.request_fileno)
39734eeed42901666fce099947f93dfdfc05411f286Martin Panter
39834eeed42901666fce099947f93dfdfc05411f286Martin Panter    @unittest.skipUnless(threading, 'Threading required for this test.')
39934eeed42901666fce099947f93dfdfc05411f286Martin Panter    def test_write(self):
40034eeed42901666fce099947f93dfdfc05411f286Martin Panter        # Test that wfile.write() sends data immediately, and that it does
40134eeed42901666fce099947f93dfdfc05411f286Martin Panter        # not truncate sends when interrupted by a Unix signal
40234eeed42901666fce099947f93dfdfc05411f286Martin Panter        pthread_kill = test.support.get_attribute(signal, 'pthread_kill')
40334eeed42901666fce099947f93dfdfc05411f286Martin Panter
40434eeed42901666fce099947f93dfdfc05411f286Martin Panter        class Handler(socketserver.StreamRequestHandler):
40534eeed42901666fce099947f93dfdfc05411f286Martin Panter            def handle(self):
40634eeed42901666fce099947f93dfdfc05411f286Martin Panter                self.server.sent1 = self.wfile.write(b'write data\n')
40734eeed42901666fce099947f93dfdfc05411f286Martin Panter                # Should be sent immediately, without requiring flush()
40834eeed42901666fce099947f93dfdfc05411f286Martin Panter                self.server.received = self.rfile.readline()
4095f1a5187f72acb75d59fa67286ecf5c186bae619Serhiy Storchaka                big_chunk = b'\0' * test.support.SOCK_MAX_SIZE
41034eeed42901666fce099947f93dfdfc05411f286Martin Panter                self.server.sent2 = self.wfile.write(big_chunk)
41134eeed42901666fce099947f93dfdfc05411f286Martin Panter
41234eeed42901666fce099947f93dfdfc05411f286Martin Panter        server = socketserver.TCPServer((HOST, 0), Handler)
41334eeed42901666fce099947f93dfdfc05411f286Martin Panter        self.addCleanup(server.server_close)
41434eeed42901666fce099947f93dfdfc05411f286Martin Panter        interrupted = threading.Event()
41534eeed42901666fce099947f93dfdfc05411f286Martin Panter
41634eeed42901666fce099947f93dfdfc05411f286Martin Panter        def signal_handler(signum, frame):
41734eeed42901666fce099947f93dfdfc05411f286Martin Panter            interrupted.set()
41834eeed42901666fce099947f93dfdfc05411f286Martin Panter
41934eeed42901666fce099947f93dfdfc05411f286Martin Panter        original = signal.signal(signal.SIGUSR1, signal_handler)
42034eeed42901666fce099947f93dfdfc05411f286Martin Panter        self.addCleanup(signal.signal, signal.SIGUSR1, original)
42134eeed42901666fce099947f93dfdfc05411f286Martin Panter        response1 = None
42234eeed42901666fce099947f93dfdfc05411f286Martin Panter        received2 = None
42334eeed42901666fce099947f93dfdfc05411f286Martin Panter        main_thread = threading.get_ident()
42434eeed42901666fce099947f93dfdfc05411f286Martin Panter
42534eeed42901666fce099947f93dfdfc05411f286Martin Panter        def run_client():
42634eeed42901666fce099947f93dfdfc05411f286Martin Panter            s = socket.socket(server.address_family, socket.SOCK_STREAM,
42734eeed42901666fce099947f93dfdfc05411f286Martin Panter                socket.IPPROTO_TCP)
42834eeed42901666fce099947f93dfdfc05411f286Martin Panter            with s, s.makefile('rb') as reader:
42934eeed42901666fce099947f93dfdfc05411f286Martin Panter                s.connect(server.server_address)
43034eeed42901666fce099947f93dfdfc05411f286Martin Panter                nonlocal response1
43134eeed42901666fce099947f93dfdfc05411f286Martin Panter                response1 = reader.readline()
43234eeed42901666fce099947f93dfdfc05411f286Martin Panter                s.sendall(b'client response\n')
43334eeed42901666fce099947f93dfdfc05411f286Martin Panter
43434eeed42901666fce099947f93dfdfc05411f286Martin Panter                reader.read(100)
43534eeed42901666fce099947f93dfdfc05411f286Martin Panter                # The main thread should now be blocking in a send() syscall.
43634eeed42901666fce099947f93dfdfc05411f286Martin Panter                # But in theory, it could get interrupted by other signals,
43734eeed42901666fce099947f93dfdfc05411f286Martin Panter                # and then retried. So keep sending the signal in a loop, in
43834eeed42901666fce099947f93dfdfc05411f286Martin Panter                # case an earlier signal happens to be delivered at an
43934eeed42901666fce099947f93dfdfc05411f286Martin Panter                # inconvenient moment.
44034eeed42901666fce099947f93dfdfc05411f286Martin Panter                while True:
44134eeed42901666fce099947f93dfdfc05411f286Martin Panter                    pthread_kill(main_thread, signal.SIGUSR1)
44234eeed42901666fce099947f93dfdfc05411f286Martin Panter                    if interrupted.wait(timeout=float(1)):
44334eeed42901666fce099947f93dfdfc05411f286Martin Panter                        break
44434eeed42901666fce099947f93dfdfc05411f286Martin Panter                nonlocal received2
44534eeed42901666fce099947f93dfdfc05411f286Martin Panter                received2 = len(reader.read())
44634eeed42901666fce099947f93dfdfc05411f286Martin Panter
44734eeed42901666fce099947f93dfdfc05411f286Martin Panter        background = threading.Thread(target=run_client)
44834eeed42901666fce099947f93dfdfc05411f286Martin Panter        background.start()
44934eeed42901666fce099947f93dfdfc05411f286Martin Panter        server.handle_request()
45034eeed42901666fce099947f93dfdfc05411f286Martin Panter        background.join()
45134eeed42901666fce099947f93dfdfc05411f286Martin Panter        self.assertEqual(server.sent1, len(response1))
45234eeed42901666fce099947f93dfdfc05411f286Martin Panter        self.assertEqual(response1, b'write data\n')
45334eeed42901666fce099947f93dfdfc05411f286Martin Panter        self.assertEqual(server.received, b'client response\n')
45434eeed42901666fce099947f93dfdfc05411f286Martin Panter        self.assertEqual(server.sent2, test.support.SOCK_MAX_SIZE)
45534eeed42901666fce099947f93dfdfc05411f286Martin Panter        self.assertEqual(received2, test.support.SOCK_MAX_SIZE - 100)
45634eeed42901666fce099947f93dfdfc05411f286Martin Panter
45734eeed42901666fce099947f93dfdfc05411f286Martin Panter
4583265344a85a2bac749230c2d6ef1b20edcd63906Berker Peksagclass MiscTestCase(unittest.TestCase):
4593265344a85a2bac749230c2d6ef1b20edcd63906Berker Peksag
4603265344a85a2bac749230c2d6ef1b20edcd63906Berker Peksag    def test_all(self):
4613265344a85a2bac749230c2d6ef1b20edcd63906Berker Peksag        # objects defined in the module should be in __all__
4623265344a85a2bac749230c2d6ef1b20edcd63906Berker Peksag        expected = []
4633265344a85a2bac749230c2d6ef1b20edcd63906Berker Peksag        for name in dir(socketserver):
4643265344a85a2bac749230c2d6ef1b20edcd63906Berker Peksag            if not name.startswith('_'):
4653265344a85a2bac749230c2d6ef1b20edcd63906Berker Peksag                mod_object = getattr(socketserver, name)
4663265344a85a2bac749230c2d6ef1b20edcd63906Berker Peksag                if getattr(mod_object, '__module__', None) == 'socketserver':
4673265344a85a2bac749230c2d6ef1b20edcd63906Berker Peksag                    expected.append(name)
4683265344a85a2bac749230c2d6ef1b20edcd63906Berker Peksag        self.assertCountEqual(socketserver.__all__, expected)
469a9f6f22f72833e49d01539f37effab67aa21391bTim Peters
4704bf427495fc65f331ae11903b57f6aa712a35ee3Martin Panter    def test_shutdown_request_called_if_verify_request_false(self):
4714bf427495fc65f331ae11903b57f6aa712a35ee3Martin Panter        # Issue #26309: BaseServer should call shutdown_request even if
4724bf427495fc65f331ae11903b57f6aa712a35ee3Martin Panter        # verify_request is False
4734bf427495fc65f331ae11903b57f6aa712a35ee3Martin Panter
4744bf427495fc65f331ae11903b57f6aa712a35ee3Martin Panter        class MyServer(socketserver.TCPServer):
4754bf427495fc65f331ae11903b57f6aa712a35ee3Martin Panter            def verify_request(self, request, client_address):
4764bf427495fc65f331ae11903b57f6aa712a35ee3Martin Panter                return False
4774bf427495fc65f331ae11903b57f6aa712a35ee3Martin Panter
4784bf427495fc65f331ae11903b57f6aa712a35ee3Martin Panter            shutdown_called = 0
4794bf427495fc65f331ae11903b57f6aa712a35ee3Martin Panter            def shutdown_request(self, request):
4804bf427495fc65f331ae11903b57f6aa712a35ee3Martin Panter                self.shutdown_called += 1
4814bf427495fc65f331ae11903b57f6aa712a35ee3Martin Panter                socketserver.TCPServer.shutdown_request(self, request)
4824bf427495fc65f331ae11903b57f6aa712a35ee3Martin Panter
4834bf427495fc65f331ae11903b57f6aa712a35ee3Martin Panter        server = MyServer((HOST, 0), socketserver.StreamRequestHandler)
4844bf427495fc65f331ae11903b57f6aa712a35ee3Martin Panter        s = socket.socket(server.address_family, socket.SOCK_STREAM)
4854bf427495fc65f331ae11903b57f6aa712a35ee3Martin Panter        s.connect(server.server_address)
4864bf427495fc65f331ae11903b57f6aa712a35ee3Martin Panter        s.close()
4874bf427495fc65f331ae11903b57f6aa712a35ee3Martin Panter        server.handle_request()
4884bf427495fc65f331ae11903b57f6aa712a35ee3Martin Panter        self.assertEqual(server.shutdown_called, 1)
4894bf427495fc65f331ae11903b57f6aa712a35ee3Martin Panter        server.server_close()
4904bf427495fc65f331ae11903b57f6aa712a35ee3Martin Panter
49139f1b3656ed1fdd98d908a21e1b0aafa6b4e75c4Guido van Rossum
492a9f6f22f72833e49d01539f37effab67aa21391bTim Petersif __name__ == "__main__":
4933265344a85a2bac749230c2d6ef1b20edcd63906Berker Peksag    unittest.main()
494