Innovenergy_trunk/NodeRed/NodeRedFiles/pika-0.13.1/tests/unit/connection_tests.py

908 lines
37 KiB
Python
Raw Normal View History

2024-06-05 10:33:44 +00:00
"""
Tests for pika.connection.Connection
"""
# Suppress pylint warnings concerning access to protected member
# pylint: disable=W0212
# Suppress pylint messages concerning missing docstrings
# pylint: disable=C0111
# Suppress pylint messages concerning invalid method name
# pylint: disable=C0103
try:
import mock
except ImportError:
from unittest import mock # pylint: disable=E0611
import random
import platform
import unittest
import mock
from pika import connection, channel, credentials, exceptions, frame, spec
import pika
from pika.compat import xrange
def callback_method():
"""Callback method to use in tests"""
pass
class ConnectionTests(unittest.TestCase): # pylint: disable=R0904
def setUp(self):
class ChannelTemplate(channel.Channel):
channel_number = None
with mock.patch('pika.connection.Connection.connect'):
self.connection = connection.Connection()
self.connection._set_connection_state(
connection.Connection.CONNECTION_OPEN)
self.channel = mock.Mock(spec=ChannelTemplate)
self.channel.channel_number = 1
self.channel.is_open = True
self.channel.is_closing = False
self.channel.is_closed = False
self.connection._channels[self.channel.channel_number] = self.channel
def tearDown(self):
del self.connection
del self.channel
@mock.patch('pika.connection.Connection._on_close_ready')
def test_close_calls_on_close_ready_when_no_channels(
self, on_close_ready_mock):
self.connection._channels = dict()
self.connection.close()
self.assertTrue(on_close_ready_mock.called,
'on_close_ready_mock should have been called')
@mock.patch('pika.connection.Connection._on_close_ready')
def test_close_closes_open_channels(self, on_close_ready):
self.connection.close()
self.channel.close.assert_called_once_with(200, 'Normal shutdown')
self.assertFalse(on_close_ready.called)
@mock.patch('pika.connection.Connection._on_close_ready')
def test_close_closes_opening_channels(self, on_close_ready):
self.channel.is_open = False
self.channel.is_closing = False
self.channel.is_closed = False
self.connection.close()
self.channel.close.assert_called_once_with(200, 'Normal shutdown')
self.assertFalse(on_close_ready.called)
@mock.patch('pika.connection.Connection._on_close_ready')
def test_close_does_not_close_closing_channels(self, on_close_ready):
self.channel.is_open = False
self.channel.is_closing = True
self.channel.is_closed = False
self.connection.close()
self.assertFalse(self.channel.close.called)
self.assertFalse(on_close_ready.called)
@mock.patch('pika.connection.Connection._close_channels')
def test_close_bails_out_if_already_closed_or_closing(
self, close_channels):
for closed_state in (self.connection.CONNECTION_CLOSED,
self.connection.CONNECTION_CLOSING):
self.connection.connection_state = closed_state
self.connection.close()
self.assertFalse(self.channel.close.called)
self.assertEqual(self.connection.connection_state, closed_state)
@mock.patch('logging.Logger.critical')
def test_deliver_frame_to_channel_with_frame_for_unknown_channel(
self, critical_mock):
unknown_channel_num = 99
self.assertNotIn(unknown_channel_num, self.connection._channels)
unexpected_frame = frame.Method(unknown_channel_num, mock.Mock())
self.connection._deliver_frame_to_channel(unexpected_frame)
critical_mock.assert_called_once_with(
'Received %s frame for unregistered channel %i on %s',
unexpected_frame.NAME, unknown_channel_num, self.connection)
@mock.patch('pika.connection.Connection._on_close_ready')
def test_on_channel_cleanup_with_closing_channels(self, on_close_ready):
"""if connection is closing but closing channels remain, do not call \
_on_close_ready
"""
self.channel.is_open = False
self.channel.is_closing = True
self.channel.is_closed = False
self.connection.close()
self.assertFalse(on_close_ready.called,
'_on_close_ready should not have been called')
@mock.patch('pika.connection.Connection._on_close_ready')
def test_on_channel_cleanup_closing_state_last_channel_calls_on_close_ready(
self, on_close_ready_mock):
self.connection.connection_state = self.connection.CONNECTION_CLOSING
self.connection._on_channel_cleanup(self.channel)
self.assertTrue(on_close_ready_mock.called,
'_on_close_ready should have been called')
@mock.patch('pika.connection.Connection._on_close_ready')
def test_on_channel_cleanup_closing_state_more_channels_no_on_close_ready(
self, on_close_ready_mock):
self.connection.connection_state = self.connection.CONNECTION_CLOSING
channel_mock = mock.Mock(channel_number=99, is_closing=True)
self.connection._channels[99] = channel_mock
self.connection._on_channel_cleanup(self.channel)
self.assertFalse(on_close_ready_mock.called,
'_on_close_ready should not have been called')
@mock.patch('pika.connection.Connection._on_close_ready')
def test_on_channel_cleanup_non_closing_state(self, on_close_ready):
"""if connection isn't closing _on_close_ready should not be called"""
self.connection._on_channel_cleanup(mock.Mock())
self.assertFalse(on_close_ready.called,
'_on_close_ready should not have been called')
def test_on_terminate_cleans_up(self):
"""_on_terminate cleans up heartbeat, adapter, and channels"""
heartbeat = mock.Mock()
self.connection.heartbeat = heartbeat
self.connection._adapter_disconnect = mock.Mock()
self.connection._on_terminate(-1, 'Undefined')
heartbeat.stop.assert_called_once_with()
self.connection._adapter_disconnect.assert_called_once_with()
self.channel._on_close_meta.assert_called_once_with(-1, 'Undefined')
self.assertTrue(self.connection.is_closed)
def test_on_terminate_invokes_connection_closed_callback(self):
"""_on_terminate invokes `Connection.ON_CONNECTION_CLOSED` callbacks"""
self.connection.callbacks.process = mock.Mock(
wraps=self.connection.callbacks.process)
self.connection._adapter_disconnect = mock.Mock()
self.connection._on_terminate(1, 'error text')
self.connection.callbacks.process.assert_called_once_with(
0, self.connection.ON_CONNECTION_CLOSED, self.connection,
self.connection, 1, 'error text')
with self.assertRaises(AssertionError):
self.connection.callbacks.process.assert_any_call(
0, self.connection.ON_CONNECTION_ERROR, self.connection,
self.connection, mock.ANY)
def test_on_terminate_invokes_protocol_on_connection_error_and_closed(
self):
"""_on_terminate invokes `ON_CONNECTION_ERROR` with \
`IncompatibleProtocolError` and `ON_CONNECTION_CLOSED` callbacks"""
with mock.patch.object(self.connection.callbacks, 'process'):
self.connection._adapter_disconnect = mock.Mock()
self.connection._set_connection_state(
self.connection.CONNECTION_PROTOCOL)
self.connection._on_terminate(1, 'error text')
self.assertEqual(self.connection.callbacks.process.call_count, 2)
self.connection.callbacks.process.assert_any_call(
0, self.connection.ON_CONNECTION_ERROR, self.connection,
self.connection, mock.ANY)
conn_exc = self.connection.callbacks.process.call_args_list[0][0][
4]
self.assertIs(type(conn_exc), exceptions.IncompatibleProtocolError)
self.assertSequenceEqual(conn_exc.args, [1, 'error text'])
self.connection.callbacks.process.assert_any_call(
0, self.connection.ON_CONNECTION_CLOSED, self.connection,
self.connection, 1, 'error text')
def test_on_terminate_invokes_auth_on_connection_error_and_closed(self):
"""_on_terminate invokes `ON_CONNECTION_ERROR` with \
`ProbableAuthenticationError` and `ON_CONNECTION_CLOSED` callbacks"""
with mock.patch.object(self.connection.callbacks, 'process'):
self.connection._adapter_disconnect = mock.Mock()
self.connection._set_connection_state(
self.connection.CONNECTION_START)
self.connection._on_terminate(1, 'error text')
self.assertEqual(self.connection.callbacks.process.call_count, 2)
self.connection.callbacks.process.assert_any_call(
0, self.connection.ON_CONNECTION_ERROR, self.connection,
self.connection, mock.ANY)
conn_exc = self.connection.callbacks.process.call_args_list[0][0][
4]
self.assertIs(
type(conn_exc), exceptions.ProbableAuthenticationError)
self.assertSequenceEqual(conn_exc.args, [1, 'error text'])
self.connection.callbacks.process.assert_any_call(
0, self.connection.ON_CONNECTION_CLOSED, self.connection,
self.connection, 1, 'error text')
def test_on_terminate_invokes_access_denied_on_connection_error_and_closed(
self):
"""_on_terminate invokes `ON_CONNECTION_ERROR` with \
`ProbableAccessDeniedError` and `ON_CONNECTION_CLOSED` callbacks"""
with mock.patch.object(self.connection.callbacks, 'process'):
self.connection._adapter_disconnect = mock.Mock()
self.connection._set_connection_state(
self.connection.CONNECTION_TUNE)
self.connection._on_terminate(1, 'error text')
self.assertEqual(self.connection.callbacks.process.call_count, 2)
self.connection.callbacks.process.assert_any_call(
0, self.connection.ON_CONNECTION_ERROR, self.connection,
self.connection, mock.ANY)
conn_exc = self.connection.callbacks.process.call_args_list[0][0][
4]
self.assertIs(type(conn_exc), exceptions.ProbableAccessDeniedError)
self.assertSequenceEqual(conn_exc.args, [1, 'error text'])
self.connection.callbacks.process.assert_any_call(
0, self.connection.ON_CONNECTION_CLOSED, self.connection,
self.connection, 1, 'error text')
@mock.patch('pika.connection.Connection.connect')
def test_new_conn_should_use_first_channel(self, connect):
"""_next_channel_number in new conn should always be 1"""
conn = connection.Connection()
self.assertEqual(1, conn._next_channel_number())
def test_next_channel_number_returns_lowest_unused(self):
"""_next_channel_number must return lowest available channel number"""
for channel_num in xrange(1, 50):
self.connection._channels[channel_num] = True
expectation = random.randint(5, 49)
del self.connection._channels[expectation]
self.assertEqual(self.connection._next_channel_number(), expectation)
def test_add_callbacks(self):
"""make sure the callback adding works"""
self.connection.callbacks = mock.Mock(spec=self.connection.callbacks)
for test_method, expected_key in (
(self.connection.add_backpressure_callback,
self.connection.ON_CONNECTION_BACKPRESSURE),
(self.connection.add_on_open_callback,
self.connection.ON_CONNECTION_OPEN),
(self.connection.add_on_close_callback,
self.connection.ON_CONNECTION_CLOSED)):
self.connection.callbacks.reset_mock()
test_method(callback_method)
self.connection.callbacks.add.assert_called_once_with(
0, expected_key, callback_method, False)
def test_add_on_close_callback(self):
"""make sure the add on close callback is added"""
self.connection.callbacks = mock.Mock(spec=self.connection.callbacks)
self.connection.add_on_open_callback(callback_method)
self.connection.callbacks.add.assert_called_once_with(
0, self.connection.ON_CONNECTION_OPEN, callback_method, False)
def test_add_on_open_error_callback(self):
"""make sure the add on open error callback is added"""
self.connection.callbacks = mock.Mock(spec=self.connection.callbacks)
#Test with remove default first (also checks default is True)
self.connection.add_on_open_error_callback(callback_method)
self.connection.callbacks.remove.assert_called_once_with(
0, self.connection.ON_CONNECTION_ERROR,
self.connection._on_connection_error)
self.connection.callbacks.add.assert_called_once_with(
0, self.connection.ON_CONNECTION_ERROR, callback_method, False)
def test_channel(self):
"""test the channel method"""
self.connection._next_channel_number = mock.Mock(return_value=42)
test_channel = mock.Mock(spec=channel.Channel)
self.connection._create_channel = mock.Mock(return_value=test_channel)
self.connection._add_channel_callbacks = mock.Mock()
ret_channel = self.connection.channel(callback_method)
self.assertEqual(test_channel, ret_channel)
self.connection._create_channel.assert_called_once_with(
42, callback_method)
self.connection._add_channel_callbacks.assert_called_once_with(42)
test_channel.open.assert_called_once_with()
def test_channel_on_closed_connection_raises_connection_closed(self):
self.connection.connection_state = self.connection.CONNECTION_CLOSED
with self.assertRaises(exceptions.ConnectionClosed):
self.connection.channel(lambda *args: None)
def test_channel_on_closing_connection_raises_connection_closed(self):
self.connection.connection_state = self.connection.CONNECTION_CLOSING
with self.assertRaises(exceptions.ConnectionClosed):
self.connection.channel(lambda *args: None)
def test_channel_on_init_connection_raises_connection_closed(self):
self.connection.connection_state = self.connection.CONNECTION_INIT
with self.assertRaises(exceptions.ConnectionClosed):
self.connection.channel(lambda *args: None)
def test_channel_on_start_connection_raises_connection_closed(self):
self.connection.connection_state = self.connection.CONNECTION_START
with self.assertRaises(exceptions.ConnectionClosed):
self.connection.channel(lambda *args: None)
def test_channel_on_protocol_connection_raises_connection_closed(self):
self.connection.connection_state = self.connection.CONNECTION_PROTOCOL
with self.assertRaises(exceptions.ConnectionClosed):
self.connection.channel(lambda *args: None)
def test_channel_on_tune_connection_raises_connection_closed(self):
self.connection.connection_state = self.connection.CONNECTION_TUNE
with self.assertRaises(exceptions.ConnectionClosed):
self.connection.channel(lambda *args: None)
def test_connect_no_adapter_connect_from_constructor(self):
"""check that adapter connection with AMQP is not happening in constructor """
with mock.patch(
'pika.connection.Connection._adapter_connect',
return_value=Exception(
'_adapter_connect failed')) as adapter_connect_mock:
with mock.patch(
'pika.connection.Connection.add_timeout',
return_value='timer') as add_timeout_mock:
conn = connection.Connection()
self.assertFalse(adapter_connect_mock.called)
self.assertEqual(conn.connection_state, conn.CONNECTION_INIT)
self.assertIsNotNone(conn._connection_attempt_timer)
add_timeout_mock.assert_called_once_with(
0, conn._on_connect_timer)
def test_client_properties(self):
"""make sure client properties has some important keys"""
client_props = self.connection._client_properties
self.assertTrue(isinstance(client_props, dict))
for required_key in ('product', 'platform', 'capabilities',
'information', 'version'):
self.assertTrue(required_key in client_props,
'%s missing' % required_key)
def test_client_properties_default(self):
expectation = {
'product': connection.PRODUCT,
'platform': 'Python %s' % platform.python_version(),
'capabilities': {
'authentication_failure_close': True,
'basic.nack': True,
'connection.blocked': True,
'consumer_cancel_notify': True,
'publisher_confirms': True
},
'information': 'See http://pika.rtfd.org',
'version': pika.__version__
}
self.assertDictEqual(self.connection._client_properties, expectation)
def test_client_properties_override(self):
expectation = {
'capabilities': {
'authentication_failure_close': True,
'basic.nack': True,
'connection.blocked': True,
'consumer_cancel_notify': True,
'publisher_confirms': True
}
}
override = {
'product': 'My Product',
'platform': 'Your platform',
'version': '0.1',
'information': 'this is my app'
}
expectation.update(override)
params = connection.ConnectionParameters(client_properties=override)
with mock.patch('pika.connection.Connection.connect'):
conn = connection.Connection(params)
self.assertDictEqual(conn._client_properties, expectation)
def test_set_backpressure_multiplier(self):
"""test setting the backpressure multiplier"""
self.connection._backpressure_multiplier = None
self.connection.set_backpressure_multiplier(value=5)
self.assertEqual(5, self.connection._backpressure_multiplier)
def test_close_channels(self):
"""test closing all channels"""
self.connection.connection_state = self.connection.CONNECTION_OPEN
self.connection.callbacks = mock.Mock(spec=self.connection.callbacks)
opening_channel = mock.Mock(
is_open=False, is_closed=False, is_closing=False)
open_channel = mock.Mock(
is_open=True, is_closed=False, is_closing=False)
closing_channel = mock.Mock(
is_open=False, is_closed=False, is_closing=True)
self.connection._channels = {
'openingc': opening_channel,
'openc': open_channel,
'closingc': closing_channel
}
self.connection._close_channels(400, 'reply text')
opening_channel.close.assert_called_once_with(400, 'reply text')
open_channel.close.assert_called_once_with(400, 'reply text')
self.assertFalse(closing_channel.close.called)
self.assertTrue('openingc' in self.connection._channels)
self.assertTrue('openc' in self.connection._channels)
self.assertTrue('closingc' in self.connection._channels)
self.assertFalse(self.connection.callbacks.cleanup.called)
# Test on closed connection
self.connection.connection_state = self.connection.CONNECTION_CLOSED
with self.assertRaises(AssertionError):
self.connection._close_channels(200, 'reply text')
@mock.patch('pika.frame.ProtocolHeader')
def test_on_connect_timer(self, frame_protocol_header):
"""make sure the connect method sets the state and sends a frame"""
self.connection.connection_state = self.connection.CONNECTION_INIT
self.connection._adapter_connect = mock.Mock(return_value=None)
self.connection._send_frame = mock.Mock()
frame_protocol_header.spec = frame.ProtocolHeader
frame_protocol_header.return_value = 'frame object'
self.connection._on_connect_timer()
self.assertEqual(self.connection.CONNECTION_PROTOCOL,
self.connection.connection_state)
self.connection._send_frame.assert_called_once_with('frame object')
def test_on_connect_timer_reconnect(self):
"""try the different reconnect logic, check state & other class vars"""
self.connection.connection_state = self.connection.CONNECTION_INIT
self.connection._adapter_connect = mock.Mock(return_value='error')
self.connection.callbacks = mock.Mock(spec=self.connection.callbacks)
self.connection.remaining_connection_attempts = 2
self.connection.params.retry_delay = 555
self.connection.params.connection_attempts = 99
self.connection.add_timeout = mock.Mock()
#first failure
self.connection._on_connect_timer()
self.connection.add_timeout.assert_called_once_with(
555, self.connection._on_connect_timer)
self.assertEqual(1, self.connection.remaining_connection_attempts)
self.assertFalse(self.connection.callbacks.process.called)
self.assertEqual(self.connection.CONNECTION_INIT,
self.connection.connection_state)
#fail with no attempts remaining
self.connection.add_timeout.reset_mock()
self.connection._on_connect_timer()
self.assertFalse(self.connection.add_timeout.called)
self.assertEqual(99, self.connection.remaining_connection_attempts)
self.connection.callbacks.process.assert_called_once_with(
0, self.connection.ON_CONNECTION_ERROR, self.connection,
self.connection, 'error')
self.assertEqual(self.connection.CONNECTION_CLOSED,
self.connection.connection_state)
def test_on_connection_start(self):
"""make sure starting a connection sets the correct class vars"""
method_frame = mock.Mock()
method_frame.method = mock.Mock()
method_frame.method.mechanisms = str(credentials.PlainCredentials.TYPE)
method_frame.method.version_major = 0
method_frame.method.version_minor = 9
#This may be incorrectly mocked, or the code is wrong
#TODO: Code does hasattr check, should this be a has_key/in check?
method_frame.method.server_properties = {
'capabilities': {
'basic.nack': True,
'consumer_cancel_notify': False,
'exchange_exchange_bindings': False
}
}
#This will be called, but shoudl not be implmented here, just mock it
self.connection._flush_outbound = mock.Mock()
self.connection._on_connection_start(method_frame)
self.assertEqual(True, self.connection.basic_nack)
self.assertEqual(False, self.connection.consumer_cancel_notify)
self.assertEqual(False, self.connection.exchange_exchange_bindings)
self.assertEqual(False, self.connection.publisher_confirms)
@mock.patch('pika.heartbeat.HeartbeatChecker')
@mock.patch('pika.frame.Method')
def test_on_connection_tune(self, method, heartbeat_checker):
"""make sure on connection tune turns the connection params"""
heartbeat_checker.return_value = 'hearbeat obj'
self.connection._flush_outbound = mock.Mock()
marshal = mock.Mock(return_value='ab')
method.return_value = mock.Mock(marshal=marshal)
#may be good to test this here, but i don't want to test too much
self.connection._rpc = mock.Mock()
method_frame = mock.Mock()
method_frame.method = mock.Mock()
method_frame.method.channel_max = 40
method_frame.method.frame_max = 10000
method_frame.method.heartbeat = 10
self.connection.params.channel_max = 20
self.connection.params.frame_max = 20000
self.connection.params.heartbeat = 20
#Test
self.connection._on_connection_tune(method_frame)
#verfy
self.assertEqual(self.connection.CONNECTION_TUNE,
self.connection.connection_state)
self.assertEqual(20, self.connection.params.channel_max)
self.assertEqual(10000, self.connection.params.frame_max)
self.assertEqual(20, self.connection.params.heartbeat)
self.assertEqual(9992, self.connection._body_max_length)
heartbeat_checker.assert_called_once_with(self.connection, 20)
self.assertEqual(['ab'], list(self.connection.outbound_buffer))
self.assertEqual('hearbeat obj', self.connection.heartbeat)
# Pika gives precendence to client heartbeat values if set
# See pika/pika#965.
# Both client and server values set. Pick client value
method_frame.method.heartbeat = 60
self.connection.params.heartbeat = 20
#Test
self.connection._on_connection_tune(method_frame)
#verfy
self.assertEqual(20, self.connection.params.heartbeat)
# Client value is None, use the server's
method_frame.method.heartbeat = 500
self.connection.params.heartbeat = None
#Test
self.connection._on_connection_tune(method_frame)
#verfy
self.assertEqual(500, self.connection.params.heartbeat)
# Client value is 0, use it
method_frame.method.heartbeat = 60
self.connection.params.heartbeat = 0
#Test
self.connection._on_connection_tune(method_frame)
#verfy
self.assertEqual(0, self.connection.params.heartbeat)
# Server value is 0, client value is None
method_frame.method.heartbeat = 0
self.connection.params.heartbeat = None
#Test
self.connection._on_connection_tune(method_frame)
#verfy
self.assertEqual(0, self.connection.params.heartbeat)
# Both client and server values are 0
method_frame.method.heartbeat = 0
self.connection.params.heartbeat = 0
#Test
self.connection._on_connection_tune(method_frame)
#verfy
self.assertEqual(0, self.connection.params.heartbeat)
# Server value is 0, use the client's
method_frame.method.heartbeat = 0
self.connection.params.heartbeat = 60
#Test
self.connection._on_connection_tune(method_frame)
#verfy
self.assertEqual(60, self.connection.params.heartbeat)
# Server value is 10, client passes a heartbeat function that
# chooses max(servervalue,60). Pick 60
def choose_max(conn, val):
self.assertIs(conn, self.connection)
self.assertEqual(val, 10)
return max(val, 60)
method_frame.method.heartbeat = 10
self.connection.params.heartbeat = choose_max
#Test
self.connection._on_connection_tune(method_frame)
#verfy
self.assertEqual(60, self.connection.params.heartbeat)
def test_on_connection_closed(self):
"""make sure connection close sends correct frames"""
method_frame = mock.Mock()
method_frame.method = mock.Mock(spec=spec.Connection.Close)
method_frame.method.reply_code = 1
method_frame.method.reply_text = 'hello'
self.connection._on_terminate = mock.Mock()
self.connection._on_connection_close(method_frame)
#Check
self.connection._on_terminate.assert_called_once_with(1, 'hello')
def test_on_connection_close_ok(self):
"""make sure _on_connection_close_ok terminates connection"""
method_frame = mock.Mock()
method_frame.method = mock.Mock(spec=spec.Connection.CloseOk)
self.connection.closing = (1, 'bye')
self.connection._on_terminate = mock.Mock()
self.connection._on_connection_close_ok(method_frame)
#Check
self.connection._on_terminate.assert_called_once_with(1, 'bye')
@mock.patch('pika.frame.decode_frame')
def test_on_data_available(self, decode_frame):
"""test on data available and process frame"""
data_in = ['data']
self.connection._frame_buffer = ['old_data']
for frame_type in (frame.Method, spec.Basic.Deliver, frame.Heartbeat):
frame_value = mock.Mock(spec=frame_type)
frame_value.frame_type = 2
frame_value.method = 2
frame_value.channel_number = 1
self.connection.bytes_received = 0
self.connection.heartbeat = mock.Mock()
self.connection.frames_received = 0
decode_frame.return_value = (2, frame_value)
self.connection._on_data_available(data_in)
#test value
self.assertListEqual([], self.connection._frame_buffer)
self.assertEqual(2, self.connection.bytes_received)
self.assertEqual(1, self.connection.frames_received)
if frame_type == frame.Heartbeat:
self.assertTrue(self.connection.heartbeat.received.called)
@mock.patch.object(
connection.Connection,
'connect',
spec_set=connection.Connection.connect)
@mock.patch.object(connection.Connection,
'add_on_connection_blocked_callback')
@mock.patch.object(connection.Connection,
'add_on_connection_unblocked_callback')
def test_create_with_blocked_connection_timeout_config(
self, add_on_unblocked_callback_mock, add_on_blocked_callback_mock,
connect_mock):
conn = connection.Connection(
parameters=connection.ConnectionParameters(
blocked_connection_timeout=60))
# Check
conn.add_on_connection_blocked_callback.assert_called_once_with(
conn._on_connection_blocked)
conn.add_on_connection_unblocked_callback.assert_called_once_with(
conn._on_connection_unblocked)
@mock.patch.object(connection.Connection, 'add_timeout')
@mock.patch.object(
connection.Connection,
'connect',
spec_set=connection.Connection.connect)
def test_connection_blocked_sets_timer(self, connect_mock,
add_timeout_mock):
conn = connection.Connection(
parameters=connection.ConnectionParameters(
blocked_connection_timeout=60))
conn._on_connection_blocked(
mock.Mock(name='frame.Method(Connection.Blocked)'))
# Check
conn.add_timeout.assert_called_once_with(
60, conn._on_blocked_connection_timeout)
self.assertIsNotNone(conn._blocked_conn_timer)
@mock.patch.object(connection.Connection, 'add_timeout')
@mock.patch.object(
connection.Connection,
'connect',
spec_set=connection.Connection.connect)
def test_blocked_connection_multiple_blocked_in_a_row_sets_timer_once(
self, connect_mock, add_timeout_mock):
conn = connection.Connection(
parameters=connection.ConnectionParameters(
blocked_connection_timeout=60))
# Simulate Connection.Blocked trigger
conn._on_connection_blocked(
mock.Mock(name='frame.Method(Connection.Blocked)'))
# Check
conn.add_timeout.assert_called_once_with(
60, conn._on_blocked_connection_timeout)
self.assertIsNotNone(conn._blocked_conn_timer)
timer = conn._blocked_conn_timer
# Simulate Connection.Blocked trigger again
conn._on_connection_blocked(
mock.Mock(name='frame.Method(Connection.Blocked)'))
self.assertEqual(conn.add_timeout.call_count, 1)
self.assertIs(conn._blocked_conn_timer, timer)
@mock.patch.object(connection.Connection, '_on_terminate')
@mock.patch.object(
connection.Connection,
'add_timeout',
spec_set=connection.Connection.add_timeout)
@mock.patch.object(
connection.Connection,
'connect',
spec_set=connection.Connection.connect)
def test_blocked_connection_timeout_teminates_connection(
self, connect_mock, add_timeout_mock, on_terminate_mock):
conn = connection.Connection(
parameters=connection.ConnectionParameters(
blocked_connection_timeout=60))
conn._on_connection_blocked(
mock.Mock(name='frame.Method(Connection.Blocked)'))
conn._on_blocked_connection_timeout()
# Check
conn._on_terminate.assert_called_once_with(
connection.InternalCloseReasons.BLOCKED_CONNECTION_TIMEOUT,
'Blocked connection timeout expired')
self.assertIsNone(conn._blocked_conn_timer)
@mock.patch.object(connection.Connection, 'remove_timeout')
@mock.patch.object(
connection.Connection,
'add_timeout',
spec_set=connection.Connection.add_timeout)
@mock.patch.object(
connection.Connection,
'connect',
spec_set=connection.Connection.connect)
def test_blocked_connection_unblocked_removes_timer(
self, connect_mock, add_timeout_mock, remove_timeout_mock):
conn = connection.Connection(
parameters=connection.ConnectionParameters(
blocked_connection_timeout=60))
conn._on_connection_blocked(
mock.Mock(name='frame.Method(Connection.Blocked)'))
self.assertIsNotNone(conn._blocked_conn_timer)
timer = conn._blocked_conn_timer
conn._on_connection_unblocked(
mock.Mock(name='frame.Method(Connection.Unblocked)'))
# Check
conn.remove_timeout.assert_called_once_with(timer)
self.assertIsNone(conn._blocked_conn_timer)
@mock.patch.object(connection.Connection, 'remove_timeout')
@mock.patch.object(
connection.Connection,
'add_timeout',
spec_set=connection.Connection.add_timeout)
@mock.patch.object(
connection.Connection,
'connect',
spec_set=connection.Connection.connect)
def test_blocked_connection_multiple_unblocked_in_a_row_removes_timer_once(
self, connect_mock, add_timeout_mock, remove_timeout_mock):
conn = connection.Connection(
parameters=connection.ConnectionParameters(
blocked_connection_timeout=60))
# Simulate Connection.Blocked
conn._on_connection_blocked(
mock.Mock(name='frame.Method(Connection.Blocked)'))
self.assertIsNotNone(conn._blocked_conn_timer)
timer = conn._blocked_conn_timer
# Simulate Connection.Unblocked
conn._on_connection_unblocked(
mock.Mock(name='frame.Method(Connection.Unblocked)'))
# Check
conn.remove_timeout.assert_called_once_with(timer)
self.assertIsNone(conn._blocked_conn_timer)
# Simulate Connection.Unblocked again
conn._on_connection_unblocked(
mock.Mock(name='frame.Method(Connection.Unblocked)'))
self.assertEqual(conn.remove_timeout.call_count, 1)
self.assertIsNone(conn._blocked_conn_timer)
@mock.patch.object(connection.Connection, 'remove_timeout')
@mock.patch.object(
connection.Connection,
'add_timeout',
spec_set=connection.Connection.add_timeout)
@mock.patch.object(
connection.Connection,
'connect',
spec_set=connection.Connection.connect)
@mock.patch.object(
connection.Connection,
'_adapter_disconnect',
spec_set=connection.Connection._adapter_disconnect)
def test_blocked_connection_on_terminate_removes_timer(
self, adapter_disconnect_mock, connect_mock, add_timeout_mock,
remove_timeout_mock):
conn = connection.Connection(
parameters=connection.ConnectionParameters(
blocked_connection_timeout=60))
conn._on_connection_blocked(
mock.Mock(name='frame.Method(Connection.Blocked)'))
self.assertIsNotNone(conn._blocked_conn_timer)
timer = conn._blocked_conn_timer
conn._on_terminate(0, 'test_on_terminate_removes_timer')
# Check
conn.remove_timeout.assert_called_once_with(timer)
self.assertIsNone(conn._blocked_conn_timer)
def test_send_message_updates_frames_sent_and_bytes_sent(self):
self.connection._flush_outbound = mock.Mock()
self.connection._body_max_length = 10000
method = spec.Basic.Publish(
exchange='my-exchange', routing_key='my-route')
props = spec.BasicProperties()
body = b'b' * 1000000
self.connection._send_method(
channel_number=1, method=method, content=(props, body))
frames_sent = len(self.connection.outbound_buffer)
bytes_sent = sum(
len(frame) for frame in self.connection.outbound_buffer)
self.assertEqual(self.connection.frames_sent, frames_sent)
self.assertEqual(self.connection.bytes_sent, bytes_sent)
# Make sure _detect_backpressure doesn't throw
self.connection._detect_backpressure()