blob: af09515fac39d6e2d25e6a82f28e4b8ce0f5771e [file] [log] [blame]
Jens Geyer72a714e2025-08-26 22:12:07 +02001#
2# Licensed to the Apache Software Foundation (ASF) under one
3# or more contributor license agreements. See the NOTICE file
4# distributed with this work for additional information
5# regarding copyright ownership. The ASF licenses this file
6# to you under the Apache License, Version 2.0 (the
7# "License"); you may not use this file except in compliance
8# with the License. You may obtain a copy of the License at
9#
10# http://www.apache.org/licenses/LICENSE-2.0
11#
12# Unless required by applicable law or agreed to in writing,
13# software distributed under the License is distributed on an
14# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15# KIND, either express or implied. See the License for the
16# specific language governing permissions and limitations
17# under the License.
18#
19
Neil Williams01d53f42020-07-07 07:27:29 -070020import errno
21import unittest
22
23from test_sslsocket import ServerAcceptor
24
25import _import_local_thrift # noqa
26
27from thrift.transport.TSocket import TServerSocket
28from thrift.transport.TSocket import TSocket
29from thrift.transport.TTransport import TTransportException
30
31
32class TSocketTest(unittest.TestCase):
Michael Smith87079492025-11-14 13:47:42 -080033 def test_failed_connection_raises_exception(self):
34 sock = TSocket(host="localhost", port=60606) # unused port
35 with self.assertRaises(TTransportException) as ctx:
36 sock.open()
37 exc = ctx.exception
38 self.assertEqual(exc.type, TTransportException.NOT_OPEN)
39 self.assertIn("Could not connect to any of", exc.message)
40 self.assertIsNotNone(exc.inner)
41 self.assertIn("Connection refused", str(exc.inner))
42
bwangelme0ed4a1d2024-04-15 12:17:40 +080043 def test_socket_readtimeout_exception(self):
44 acc = ServerAcceptor(TServerSocket(port=0))
45 acc.start()
46
47 sock = TSocket(host="localhost", port=acc.port)
48 sock.open()
49 sock.setTimeout(1)
50 sock.write(b"sleep")
51
52 with self.assertRaises(TTransportException) as ctx:
53 sock.read(5)
54 exc = ctx.exception
55 self.assertEqual(exc.message, "read timeout")
56
57 acc.client.close() # this also blocks until the other thread is done
58 acc.close()
59 sock.close()
60
Neil Williams01d53f42020-07-07 07:27:29 -070061 def test_isOpen_checks_for_readability(self):
62 # https://docs.python.org/3/library/socket.html#notes-on-socket-timeouts
63 # https://docs.python.org/3/library/socket.html#socket.socket.settimeout
64 timeouts = [
65 None, # blocking mode
66 0, # non-blocking mode
67 1.0, # timeout mode
68 ]
69
70 for timeout in timeouts:
71 acc = ServerAcceptor(TServerSocket(port=0))
72 acc.start()
73
74 sock = TSocket(host="localhost", port=acc.port)
Michael Smithe3eb9af2022-06-08 17:23:27 -070075 self.assertFalse(sock.isOpen())
Neil Williams01d53f42020-07-07 07:27:29 -070076 sock.open()
77 sock.setTimeout(timeout)
78
79 # the socket shows as open immediately after connecting
80 self.assertTrue(sock.isOpen())
81
82 # and remains open during usage
83 sock.write(b"hello")
84 self.assertTrue(sock.isOpen())
85 while True:
86 try:
87 sock.read(5)
88 except TTransportException as exc:
89 if exc.inner.errno == errno.EAGAIN:
90 # try again when we're in non-blocking mode
91 continue
92 raise
93 break
94 self.assertTrue(sock.isOpen())
95
96 # once the server side closes, it no longer shows open
97 acc.client.close() # this also blocks until the other thread is done
98 acc.close()
Neil Williams01d53f42020-07-07 07:27:29 -070099
Csaba Ringhoferefe5e022024-08-23 14:08:35 +0200100 self.assertIsNotNone(sock.handle)
101 self.assertFalse(sock.isOpen())
102 # after isOpen() returned False the socket should be closed (THRIFT-5813)
103 self.assertIsNone(sock.handle)
Neil Williams01d53f42020-07-07 07:27:29 -0700104
105
106if __name__ == "__main__":
107 unittest.main()