|
6 | 6 | import unittest |
7 | 7 | from irods.exception import NetworkException |
8 | 8 | import irods.test.helpers as helpers |
9 | | - |
| 9 | +from irods.test.helpers import (server_side_sleep, temporarily_assign_attribute as temp_setter) |
10 | 10 |
|
11 | 11 | class TestConnections(unittest.TestCase): |
12 | 12 |
|
@@ -105,22 +105,79 @@ def test_that_connection_timeout_works__issue_377(self): |
105 | 105 | if local_file: |
106 | 106 | os.unlink(local_file.name) |
107 | 107 |
|
108 | | - def assert_timeout_value_propagated_to_socket(self, session, timeout_value): |
| 108 | + def _assert_timeout_value_is_propagated_to_all_sockets__issue_569(self, session, expected_timeout_value = 'POOL_TIMEOUT_SETTING'): |
| 109 | + pool = session.pool |
| 110 | + new_conn = None |
| 111 | + if expected_timeout_value == 'POOL_TIMEOUT_SETTING': |
| 112 | + expected_timeout_value = pool.connection_timeout |
| 113 | + connections = set() |
| 114 | + # make sure idle pool is not empty |
109 | 115 | session.collections.get(helpers.home_collection(session)) |
110 | | - conn = next(iter(session.pool.idle)) |
111 | | - self.assertEqual(conn.socket.gettimeout(), timeout_value) |
| 116 | + # On any connections thus far created, check that their internal socket objects are set to the expected timeout value. |
| 117 | + try: |
| 118 | + # Peel connections off the idle pool and check each for the expected timeout value, but don't release them to that pool yet. |
| 119 | + while (pool.idle): |
| 120 | + # Peel a connection (guaranteed newly-allocated for purposes of this test) and check for the proper timeout. |
| 121 | + conn = pool.get_connection() |
| 122 | + connections |= {conn} |
| 123 | + self.assertEqual(conn.socket.gettimeout(), expected_timeout_value) |
| 124 | + |
| 125 | + # Get an additional connection while idle pool is empty; this way, we know it to be newly-allocated. |
| 126 | + new_conn = pool.get_connection() |
| 127 | + |
| 128 | + # Check the expected timeout applies to the newly-allocated connection |
| 129 | + self.assertEqual(new_conn.socket.gettimeout(), expected_timeout_value) |
| 130 | + |
| 131 | + finally: |
| 132 | + # Release and destroy the connection that was newly-allocated for this test. |
| 133 | + if new_conn: |
| 134 | + new_conn.release(destroy = True) |
| 135 | + # Release connections that had been cached, by the same normal mechanism the API endpoints indirectly employ. |
| 136 | + for conn in connections: |
| 137 | + pool.release_connection(conn) |
112 | 138 |
|
113 | 139 | def test_connection_timeout_parameter_in_session_init__issue_377(self): |
114 | 140 | timeout = 1.0 |
115 | 141 | sess = helpers.make_session(connection_timeout = timeout) |
116 | | - self.assert_timeout_value_propagated_to_socket(sess, timeout) |
| 142 | + self._assert_timeout_value_is_propagated_to_all_sockets__issue_569(sess, timeout) |
117 | 143 |
|
118 | 144 | def test_assigning_session_connection_timeout__issue_377(self): |
119 | | - sess = self.sess |
| 145 | + sess = helpers.make_session() |
120 | 146 | for timeout in (999999, None): |
121 | 147 | sess.connection_timeout = timeout |
122 | | - sess.cleanup() |
123 | | - self.assert_timeout_value_propagated_to_socket(sess, timeout) |
| 148 | + self._assert_timeout_value_is_propagated_to_all_sockets__issue_569(sess, timeout) |
| 149 | + |
| 150 | + def test_assigning_session_connection_timeout_to_invalid_values__issue_569(self): |
| 151 | + sess = helpers.make_session() |
| 152 | + DESIRED_TIMEOUT = 64.25 |
| 153 | + sess.connection_timeout = DESIRED_TIMEOUT |
| 154 | + # Test our desired connection pool default timeout has taken hold. |
| 155 | + self.assertEqual(sess.connection_timeout, DESIRED_TIMEOUT) |
| 156 | + |
| 157 | + # Test that bad timeout values are met with an exception. |
| 158 | + for value in (float('NaN'), float('Inf'), -float('Inf'), -1, 0, 0.0, "banana"): |
| 159 | + with self.assertRaises(ValueError): |
| 160 | + sess.connection_timeout = value |
| 161 | + |
| 162 | + # Test previously set value is unaffected |
| 163 | + self.assertEqual(sess.connection_timeout, DESIRED_TIMEOUT) |
| 164 | + |
| 165 | + def test_assigning_session_connection_timeout__issue_569(self): |
| 166 | + sess = helpers.make_session() |
| 167 | + old_timeout = sess.connection_timeout |
| 168 | + |
| 169 | + with temp_setter(sess, 'connection_timeout',1.0): |
| 170 | + # verify we can reproduce a NetworkException from a server timeout |
| 171 | + with self.assertRaises(NetworkException): |
| 172 | + server_side_sleep(sess,2.5) |
| 173 | + # temporarily suspend timeouts on a session |
| 174 | + with temp_setter(sess, 'connection_timeout',None): |
| 175 | + server_side_sleep(sess,2.5) |
| 176 | + # temporarily increase (from 1.0 to 4) the timeout on a session |
| 177 | + with temp_setter(sess, 'connection_timeout',4): |
| 178 | + server_side_sleep(sess,2.5) |
| 179 | + self.assertEqual(old_timeout, sess.connection_timeout) |
| 180 | + self._assert_timeout_value_is_propagated_to_all_sockets__issue_569(sess, old_timeout) |
124 | 181 |
|
125 | 182 | if __name__ == '__main__': |
126 | 183 | # let the tests find the parent irods lib |
|
0 commit comments