kombu/t/unit/test_connection.py

893 lines
30 KiB
Python

from __future__ import annotations
import pickle
import socket
from copy import copy, deepcopy
from unittest.mock import Mock, patch
import pytest
from kombu import Connection, Consumer, Producer, parse_url
from kombu.connection import Resource
from kombu.exceptions import OperationalError
from kombu.utils.functional import lazy
from t.mocks import Transport
class test_connection_utils:
def setup(self):
self.url = 'amqp://user:pass@localhost:5672/my/vhost'
self.nopass = 'amqp://user:**@localhost:5672/my/vhost'
self.expected = {
'transport': 'amqp',
'userid': 'user',
'password': 'pass',
'hostname': 'localhost',
'port': 5672,
'virtual_host': 'my/vhost',
}
self.pg_url = 'sqla+postgresql://test:password@yms-pg/yms'
self.pg_nopass = 'sqla+postgresql://test:**@yms-pg/yms'
def test_parse_url(self):
result = parse_url(self.url)
assert result == self.expected
def test_parse_generated_as_uri(self):
conn = Connection(self.url)
info = conn.info()
for k, v in self.expected.items():
assert info[k] == v
# by default almost the same- no password
assert conn.as_uri() == self.nopass
assert conn.as_uri(include_password=True) == self.url
def test_as_uri_when_prefix(self):
pytest.importorskip('redis')
conn = Connection('redis+socket:///var/spool/x/y/z/redis.sock')
assert conn.as_uri() == 'redis+socket:///var/spool/x/y/z/redis.sock'
def test_as_uri_when_mongodb(self):
pytest.importorskip('pymongo')
x = Connection('mongodb://localhost')
assert x.as_uri()
def test_bogus_scheme(self):
with pytest.raises(KeyError):
Connection('bogus://localhost:7421').transport
def assert_info(self, conn, **fields):
info = conn.info()
for field, expected in fields.items():
assert info[field] == expected
@pytest.mark.parametrize('url,expected', [
('amqp://user:pass@host:10000/vhost',
{'userid': 'user', 'password': 'pass', 'hostname': 'host',
'port': 10000, 'virtual_host': 'vhost'}),
('amqp://user%61:%61pass@ho%61st:10000/v%2fhost',
{'userid': 'usera', 'password': 'apass', 'hostname': 'hoast',
'port': 10000, 'virtual_host': 'v/host'}),
('amqp://',
{'userid': 'guest', 'password': 'guest', 'hostname': 'localhost',
'port': 5672, 'virtual_host': '/'}),
('amqp://:@/',
{'userid': 'guest', 'password': 'guest', 'hostname': 'localhost',
'port': 5672, 'virtual_host': '/'}),
('amqp://user@/',
{'userid': 'user', 'password': 'guest', 'hostname': 'localhost',
'port': 5672, 'virtual_host': '/'}),
('amqp://user:pass@/',
{'userid': 'user', 'password': 'pass', 'hostname': 'localhost',
'port': 5672, 'virtual_host': '/'}),
('amqp://host',
{'userid': 'guest', 'password': 'guest', 'hostname': 'host',
'port': 5672, 'virtual_host': '/'}),
('amqp://:10000',
{'userid': 'guest', 'password': 'guest', 'hostname': 'localhost',
'port': 10000, 'virtual_host': '/'}),
('amqp:///vhost',
{'userid': 'guest', 'password': 'guest', 'hostname': 'localhost',
'port': 5672, 'virtual_host': 'vhost'}),
('amqp://host/',
{'userid': 'guest', 'password': 'guest', 'hostname': 'host',
'port': 5672, 'virtual_host': '/'}),
('amqp://host/%2f',
{'userid': 'guest', 'password': 'guest', 'hostname': 'host',
'port': 5672, 'virtual_host': '/'}),
])
def test_rabbitmq_example_urls(self, url, expected):
# see Appendix A of http://www.rabbitmq.com/uri-spec.html
self.assert_info(Connection(url), **expected)
@pytest.mark.parametrize('url,expected', [
('sqs://user:pass@',
{'userid': None, 'password': None, 'hostname': None,
'port': None, 'virtual_host': '/'}),
('sqs://',
{'userid': None, 'password': None, 'hostname': None,
'port': None, 'virtual_host': '/'}),
])
def test_sqs_example_urls(self, url, expected, caplog):
pytest.importorskip('boto3')
self.assert_info(Connection('sqs://'), **expected)
assert not caplog.records
@pytest.mark.skip('TODO: urllib cannot parse ipv6 urls')
def test_url_IPV6(self):
self.assert_info(
Connection('amqp://[::1]'),
userid='guest', password='guest', hostname='[::1]',
port=5672, virtual_host='/',
)
def test_connection_copy(self):
conn = Connection(self.url, alternates=['amqp://host'])
clone = deepcopy(conn)
assert clone.alt == ['amqp://host']
def test_parse_generated_as_uri_pg(self):
pytest.importorskip('sqlalchemy')
conn = Connection(self.pg_url)
assert conn.as_uri() == self.pg_nopass
assert conn.as_uri(include_password=True) == self.pg_url
class test_Connection:
def setup(self):
self.conn = Connection(port=5672, transport=Transport)
def test_establish_connection(self):
conn = self.conn
assert not conn.connected
conn.connect()
assert conn.connected
assert conn.connection.connected
assert conn.host == 'localhost:5672'
channel = conn.channel()
assert channel.open
assert conn.drain_events() == 'event'
_connection = conn.connection
conn.close()
assert not _connection.connected
assert isinstance(conn.transport, Transport)
def test_reuse_connection(self):
conn = self.conn
assert conn.connect() is conn.connection is conn.connect()
def test_connect_no_transport_options(self):
conn = self.conn
conn._ensure_connection = Mock()
conn.connect()
# ensure_connection must be called to return immidiately
# and fail with transport exception
conn._ensure_connection.assert_called_with(
max_retries=1, reraise_as_library_errors=False
)
def test_connect_transport_options(self):
conn = self.conn
conn.transport_options = {
'max_retries': 1,
'interval_start': 2,
'interval_step': 3,
'interval_max': 4,
'ignore_this': True
}
conn._ensure_connection = Mock()
conn.connect()
# connect() is ignoring transport options
# ensure_connection must be called to return immidiately
# and fail with transport exception
conn._ensure_connection.assert_called_with(
max_retries=1, reraise_as_library_errors=False
)
def test_multiple_urls(self):
conn1 = Connection('amqp://foo;amqp://bar')
assert conn1.hostname == 'foo'
assert conn1.alt == ['amqp://foo', 'amqp://bar']
conn2 = Connection(['amqp://foo', 'amqp://bar'])
assert conn2.hostname == 'foo'
assert conn2.alt == ['amqp://foo', 'amqp://bar']
def test_collect(self):
connection = Connection('memory://')
trans = connection._transport = Mock(name='transport')
_collect = trans._collect = Mock(name='transport._collect')
_close = connection._close = Mock(name='connection._close')
connection.declared_entities = Mock(name='decl_entities')
uconn = connection._connection = Mock(name='_connection')
connection.collect()
_close.assert_not_called()
_collect.assert_called_with(uconn)
connection.declared_entities.clear.assert_called_with()
assert trans.client is None
assert connection._transport is None
assert connection._connection is None
def test_prefer_librabbitmq_over_amqp_when_available(self):
with patch('kombu.connection.supports_librabbitmq',
return_value=True):
connection = Connection('amqp://')
assert connection.transport_cls == 'librabbitmq'
def test_select_amqp_when_librabbitmq_is_not_available(self):
with patch('kombu.connection.supports_librabbitmq',
return_value=False):
connection = Connection('amqp://')
assert connection.transport_cls == 'amqp'
def test_collect_no_transport(self):
connection = Connection('memory://')
connection._transport = None
connection._do_close_self = Mock()
connection._do_close_transport = Mock()
connection.collect()
connection._do_close_self.assert_called_with()
connection._do_close_transport.assert_called_with()
connection._do_close_self.side_effect = socket.timeout()
connection.collect()
def test_collect_transport_gone(self):
connection = Connection('memory://')
uconn = connection._connection = Mock(name='conn._conn')
trans = connection._transport = Mock(name='transport')
collect = trans._collect = Mock(name='transport._collect')
def se(conn):
connection._transport = None
collect.side_effect = se
connection.collect()
collect.assert_called_with(uconn)
assert connection._transport is None
def test_uri_passthrough(self):
transport = Mock(name='transport')
with patch('kombu.connection.get_transport_cls') as gtc:
gtc.return_value = transport
transport.can_parse_url = True
with patch('kombu.connection.parse_url') as parse_url:
c = Connection('foo+mysql://some_host')
assert c.transport_cls == 'foo'
parse_url.assert_not_called()
assert c.hostname == 'mysql://some_host'
assert c.as_uri().startswith('foo+')
with patch('kombu.connection.parse_url') as parse_url:
c = Connection('mysql://some_host', transport='foo')
assert c.transport_cls == 'foo'
parse_url.assert_not_called()
assert c.hostname == 'mysql://some_host'
c = Connection('pyamqp+sqlite://some_host')
assert c.as_uri().startswith('pyamqp+')
def test_ensure_connection_on_error(self):
c = Connection('amqp://A;amqp://B')
with patch('kombu.connection.retry_over_time') as rot:
c.ensure_connection()
rot.assert_called()
args = rot.call_args[0]
cb = args[4]
intervals = iter([1, 2, 3, 4, 5])
assert cb(KeyError(), intervals, 0) == 0
assert cb(KeyError(), intervals, 1) == 1
assert cb(KeyError(), intervals, 2) == 0
assert cb(KeyError(), intervals, 3) == 2
assert cb(KeyError(), intervals, 4) == 0
assert cb(KeyError(), intervals, 5) == 3
assert cb(KeyError(), intervals, 6) == 0
assert cb(KeyError(), intervals, 7) == 4
errback = Mock()
c.ensure_connection(errback=errback)
args = rot.call_args[0]
cb = args[4]
assert cb(KeyError(), intervals, 0) == 0
errback.assert_called()
def test_supports_heartbeats(self):
c = Connection(transport=Mock)
c.transport.implements.heartbeats = False
assert not c.supports_heartbeats
def test_is_evented(self):
c = Connection(transport=Mock)
c.transport.implements.asynchronous = False
assert not c.is_evented
def test_register_with_event_loop(self):
transport = Mock(name='transport')
transport.connection_errors = []
c = Connection(transport=transport)
loop = Mock(name='loop')
c.register_with_event_loop(loop)
c.transport.register_with_event_loop.assert_called_with(
c.connection, loop,
)
def test_manager(self):
c = Connection(transport=Mock)
assert c.manager is c.transport.manager
def test_copy(self):
c = Connection('amqp://example.com')
assert copy(c).info() == c.info()
def test_copy_multiples(self):
c = Connection('amqp://A.example.com;amqp://B.example.com')
assert c.alt
d = copy(c)
assert d.alt == c.alt
def test_switch(self):
c = Connection('amqp://foo')
c._closed = True
c.switch('redis://example.com//3')
assert not c._closed
assert c.hostname == 'example.com'
assert c.transport_cls == 'redis'
assert c.virtual_host == '/3'
def test_maybe_switch_next(self):
c = Connection('amqp://foo;redis://example.com//3')
c.maybe_switch_next()
assert not c._closed
assert c.hostname == 'example.com'
assert c.transport_cls == 'redis'
assert c.virtual_host == '/3'
def test_maybe_switch_next_no_cycle(self):
c = Connection('amqp://foo')
c.maybe_switch_next()
assert not c._closed
assert c.hostname == 'foo'
assert c.transport_cls, ('librabbitmq', 'pyamqp' in 'amqp')
def test_switch_without_uri_identifier(self):
c = Connection('amqp://foo')
assert c.hostname == 'foo'
assert c.transport_cls, ('librabbitmq', 'pyamqp' in 'amqp')
c._closed = True
c.switch('example.com')
assert not c._closed
assert c.hostname == 'example.com'
assert c.transport_cls, ('librabbitmq', 'pyamqp' in 'amqp')
def test_heartbeat_check(self):
c = Connection(transport=Transport)
c.transport.heartbeat_check = Mock()
c.heartbeat_check(3)
c.transport.heartbeat_check.assert_called_with(c.connection, rate=3)
def test_completes_cycle_no_cycle(self):
c = Connection('amqp://')
assert c.completes_cycle(0)
assert c.completes_cycle(1)
def test_completes_cycle(self):
c = Connection('amqp://a;amqp://b;amqp://c')
assert not c.completes_cycle(0)
assert not c.completes_cycle(1)
assert c.completes_cycle(2)
def test_get_heartbeat_interval(self):
self.conn.transport.get_heartbeat_interval = Mock(name='ghi')
assert (self.conn.get_heartbeat_interval() is
self.conn.transport.get_heartbeat_interval.return_value)
self.conn.transport.get_heartbeat_interval.assert_called_with(
self.conn.connection)
def test_supports_exchange_type(self):
self.conn.transport.implements.exchange_type = {'topic'}
assert self.conn.supports_exchange_type('topic')
assert not self.conn.supports_exchange_type('fanout')
def test_qos_semantics_matches_spec(self):
qsms = self.conn.transport.qos_semantics_matches_spec = Mock()
assert self.conn.qos_semantics_matches_spec is qsms.return_value
qsms.assert_called_with(self.conn.connection)
def test__enter____exit__(self):
with self.conn as context:
assert context is self.conn
self.conn.connect()
assert self.conn.connection.connected
assert self.conn.connection is None
self.conn.close() # again
def test_close_survives_connerror(self):
class _CustomError(Exception):
pass
class MyTransport(Transport):
connection_errors = (_CustomError,)
def close_connection(self, connection):
raise _CustomError('foo')
conn = Connection(transport=MyTransport)
conn.connect()
conn.close()
assert conn._closed
def test_close_when_default_channel(self):
conn = self.conn
conn._default_channel = Mock()
conn._close()
conn._default_channel.close.assert_called_with()
def test_auto_reconnect_default_channel(self):
# tests GH issue: #1208
# Tests that default_channel automatically reconnects when connection
# closed
c = Connection('memory://')
c._closed = True
with patch.object(
c, '_connection_factory', side_effect=c._connection_factory
) as cf_mock:
c.default_channel
cf_mock.assert_called_once_with()
def test_close_when_default_channel_close_raises(self):
class Conn(Connection):
@property
def connection_errors(self):
return (KeyError,)
conn = Conn('memory://')
conn._default_channel = Mock()
conn._default_channel.close.side_effect = KeyError()
conn._close()
conn._default_channel.close.assert_called_with()
def test_revive_when_default_channel(self):
conn = self.conn
defchan = conn._default_channel = Mock()
conn.revive(Mock())
defchan.close.assert_called_with()
assert conn._default_channel is None
def test_ensure_connection(self):
assert self.conn.ensure_connection()
def test_ensure_success(self):
def publish():
return 'foobar'
ensured = self.conn.ensure(None, publish)
assert ensured() == 'foobar'
def test_ensure_failure(self):
class _CustomError(Exception):
pass
def publish():
raise _CustomError('bar')
ensured = self.conn.ensure(None, publish)
with pytest.raises(_CustomError):
ensured()
def test_ensure_connection_failure(self):
class _ConnectionError(Exception):
pass
def publish():
raise _ConnectionError('failed connection')
self.conn.get_transport_cls().connection_errors = (_ConnectionError,)
ensured = self.conn.ensure(self.conn, publish)
with pytest.raises(OperationalError):
ensured()
def test_autoretry(self):
myfun = Mock()
self.conn.get_transport_cls().connection_errors = (KeyError,)
def on_call(*args, **kwargs):
myfun.side_effect = None
raise KeyError('foo')
myfun.side_effect = on_call
insured = self.conn.autoretry(myfun)
insured()
myfun.assert_called()
def test_SimpleQueue(self):
conn = self.conn
q = conn.SimpleQueue('foo')
assert q.channel is conn.default_channel
chan = conn.channel()
q2 = conn.SimpleQueue('foo', channel=chan)
assert q2.channel is chan
def test_SimpleBuffer(self):
conn = self.conn
q = conn.SimpleBuffer('foo')
assert q.channel is conn.default_channel
chan = conn.channel()
q2 = conn.SimpleBuffer('foo', channel=chan)
assert q2.channel is chan
def test_SimpleQueue_with_parameters(self):
conn = self.conn
q = conn.SimpleQueue(
'foo', True, {'durable': True}, {'x-queue-mode': 'lazy'},
{'durable': True, 'type': 'fanout', 'delivery_mode': 'persistent'})
assert q.queue.exchange.type == 'fanout'
assert q.queue.exchange.durable
assert not q.queue.exchange.auto_delete
delivery_mode_code = q.queue.exchange.PERSISTENT_DELIVERY_MODE
assert q.queue.exchange.delivery_mode == delivery_mode_code
assert q.queue.queue_arguments['x-queue-mode'] == 'lazy'
assert q.queue.durable
assert not q.queue.auto_delete
def test_SimpleBuffer_with_parameters(self):
conn = self.conn
q = conn.SimpleBuffer(
'foo', True, {'durable': True}, {'x-queue-mode': 'lazy'},
{'durable': True, 'type': 'fanout', 'delivery_mode': 'persistent'})
assert q.queue.exchange.type == 'fanout'
assert q.queue.exchange.durable
assert q.queue.exchange.auto_delete
delivery_mode_code = q.queue.exchange.PERSISTENT_DELIVERY_MODE
assert q.queue.exchange.delivery_mode == delivery_mode_code
assert q.queue.queue_arguments['x-queue-mode'] == 'lazy'
assert q.queue.durable
assert q.queue.auto_delete
def test_Producer(self):
conn = self.conn
assert isinstance(conn.Producer(), Producer)
assert isinstance(conn.Producer(conn.default_channel), Producer)
def test_Consumer(self):
conn = self.conn
assert isinstance(conn.Consumer(queues=[]), Consumer)
assert isinstance(
conn.Consumer(queues=[], channel=conn.default_channel),
Consumer)
def test__repr__(self):
assert repr(self.conn)
def test__reduce__(self):
x = pickle.loads(pickle.dumps(self.conn))
assert x.info() == self.conn.info()
def test_channel_errors(self):
class MyTransport(Transport):
channel_errors = (KeyError, ValueError)
conn = Connection(transport=MyTransport)
assert conn.channel_errors == (KeyError, ValueError)
def test_channel_errors__exception_no_cache(self):
"""Ensure the channel_errors can be retrieved without an initialized
transport.
"""
class MyTransport(Transport):
channel_errors = (KeyError,)
conn = Connection(transport=MyTransport)
MyTransport.__init__ = Mock(side_effect=Exception)
assert conn.channel_errors == (KeyError,)
def test_connection_errors(self):
class MyTransport(Transport):
connection_errors = (KeyError, ValueError)
conn = Connection(transport=MyTransport)
assert conn.connection_errors == (KeyError, ValueError)
def test_connection_errors__exception_no_cache(self):
"""Ensure the connection_errors can be retrieved without an
initialized transport.
"""
class MyTransport(Transport):
connection_errors = (KeyError,)
conn = Connection(transport=MyTransport)
MyTransport.__init__ = Mock(side_effect=Exception)
assert conn.connection_errors == (KeyError,)
def test_recoverable_connection_errors(self):
class MyTransport(Transport):
recoverable_connection_errors = (KeyError, ValueError)
conn = Connection(transport=MyTransport)
assert conn.recoverable_connection_errors == (KeyError, ValueError)
def test_recoverable_connection_errors__fallback(self):
"""Ensure missing recoverable_connection_errors on the Transport does
not cause a fatal error.
"""
class MyTransport(Transport):
connection_errors = (KeyError,)
channel_errors = (ValueError,)
conn = Connection(transport=MyTransport)
assert conn.recoverable_connection_errors == (KeyError, ValueError)
def test_recoverable_connection_errors__exception_no_cache(self):
"""Ensure the recoverable_connection_errors can be retrieved without
an initialized transport.
"""
class MyTransport(Transport):
recoverable_connection_errors = (KeyError,)
conn = Connection(transport=MyTransport)
MyTransport.__init__ = Mock(side_effect=Exception)
assert conn.recoverable_connection_errors == (KeyError,)
def test_recoverable_channel_errors(self):
class MyTransport(Transport):
recoverable_channel_errors = (KeyError, ValueError)
conn = Connection(transport=MyTransport)
assert conn.recoverable_channel_errors == (KeyError, ValueError)
def test_recoverable_channel_errors__fallback(self):
"""Ensure missing recoverable_channel_errors on the Transport does not
cause a fatal error.
"""
class MyTransport(Transport):
pass
conn = Connection(transport=MyTransport)
assert conn.recoverable_channel_errors == ()
def test_recoverable_channel_errors__exception_no_cache(self):
"""Ensure the recoverable_channel_errors can be retrieved without an
initialized transport.
"""
class MyTransport(Transport):
recoverable_channel_errors = (KeyError,)
conn = Connection(transport=MyTransport)
MyTransport.__init__ = Mock(side_effect=Exception)
assert conn.recoverable_channel_errors == (KeyError,)
def test_multiple_urls_hostname(self):
conn = Connection(['example.com;amqp://example.com'])
assert conn.as_uri() == 'amqp://guest:**@example.com:5672//'
conn = Connection(['example.com', 'amqp://example.com'])
assert conn.as_uri() == 'amqp://guest:**@example.com:5672//'
conn = Connection('example.com;example.com;')
assert conn.as_uri() == 'amqp://guest:**@example.com:5672//'
def test_connection_respect_its_timeout(self):
invalid_port = 1222
with Connection(
f'amqp://guest:guest@localhost:{invalid_port}//',
transport_options={'max_retries': 2},
connect_timeout=1
) as conn:
with pytest.raises(OperationalError):
conn.default_channel
class test_Connection_with_transport_options:
transport_options = {'pool_recycler': 3600, 'echo': True}
def setup(self):
self.conn = Connection(port=5672, transport=Transport,
transport_options=self.transport_options)
def test_establish_connection(self):
conn = self.conn
assert conn.transport_options == self.transport_options
class xResource(Resource):
def setup(self):
pass
class ResourceCase:
def create_resource(self, limit):
raise NotImplementedError('subclass responsibility')
def assert_state(self, P, avail, dirty):
assert P._resource.qsize() == avail
assert len(P._dirty) == dirty
def test_setup(self):
with pytest.raises(NotImplementedError):
Resource()
def test_acquire__release(self):
P = self.create_resource(10)
self.assert_state(P, 10, 0)
chans = [P.acquire() for _ in range(10)]
self.assert_state(P, 0, 10)
with pytest.raises(P.LimitExceeded):
P.acquire()
chans.pop().release()
self.assert_state(P, 1, 9)
[chan.release() for chan in chans]
self.assert_state(P, 10, 0)
def test_acquire_prepare_raises(self):
P = self.create_resource(10)
assert len(P._resource.queue) == 10
P.prepare = Mock()
P.prepare.side_effect = IOError()
with pytest.raises(IOError):
P.acquire(block=True)
assert len(P._resource.queue) == 10
def test_acquire_no_limit(self):
P = self.create_resource(None)
P.acquire().release()
def test_replace_when_limit(self):
P = self.create_resource(10)
r = P.acquire()
P._dirty = Mock()
P.close_resource = Mock()
P.replace(r)
P._dirty.discard.assert_called_with(r)
P.close_resource.assert_called_with(r)
def test_replace_no_limit(self):
P = self.create_resource(None)
r = P.acquire()
P._dirty = Mock()
P.close_resource = Mock()
P.replace(r)
P._dirty.discard.assert_not_called()
P.close_resource.assert_called_with(r)
def test_interface_prepare(self):
x = xResource()
assert x.prepare(10) == 10
def test_force_close_all_handles_AttributeError(self):
P = self.create_resource(10)
cr = P.collect_resource = Mock()
cr.side_effect = AttributeError('x')
P.acquire()
assert P._dirty
P.force_close_all()
def test_force_close_all_no_mutex(self):
P = self.create_resource(10)
P.close_resource = Mock()
m = P._resource = Mock()
m.mutex = None
m.queue.pop.side_effect = IndexError
P.force_close_all()
def test_add_when_empty(self):
P = self.create_resource(None)
P._resource.queue.clear()
assert not P._resource.queue
P._add_when_empty()
assert P._resource.queue
class test_ConnectionPool(ResourceCase):
def create_resource(self, limit):
return Connection(port=5672, transport=Transport).Pool(limit)
def test_collect_resource__does_not_collect_lazy_resource(self):
P = self.create_resource(10)
res = lazy(object())
res.collect = Mock(name='collect')
P.collect_resource(res)
res.collect.assert_not_called()
def test_collect_resource(self):
res = Mock(name='res')
P = self.create_resource(10)
P.collect_resource(res, socket_timeout=10.3)
res.collect.assert_called_with(10.3)
def test_setup(self):
P = self.create_resource(10)
q = P._resource.queue
assert q[0]()._connection is None
assert q[1]()._connection is None
assert q[2]()._connection is None
def test_acquire_raises_evaluated(self):
P = self.create_resource(1)
# evaluate the connection first
r = P.acquire()
r.release()
P.prepare = Mock()
P.prepare.side_effect = MemoryError()
P.release = Mock()
with pytest.raises(MemoryError):
with P.acquire():
assert False
P.release.assert_called_with(r)
def test_release_no__debug(self):
P = self.create_resource(10)
R = Mock()
R._debug.side_effect = AttributeError()
P.release_resource(R)
def test_setup_no_limit(self):
P = self.create_resource(None)
assert not P._resource.queue
assert P.limit is None
def test_prepare_not_callable(self):
P = self.create_resource(None)
conn = Connection('memory://')
assert P.prepare(conn) is conn
def test_acquire_channel(self):
P = self.create_resource(10)
with P.acquire_channel() as (conn, channel):
assert channel is conn.default_channel
class test_ChannelPool(ResourceCase):
def create_resource(self, limit):
return Connection(port=5672, transport=Transport).ChannelPool(limit)
def test_setup(self):
P = self.create_resource(10)
q = P._resource.queue
with pytest.raises(AttributeError):
q[0].basic_consume
def test_setup_no_limit(self):
P = self.create_resource(None)
assert not P._resource.queue
assert P.limit is None
def test_prepare_not_callable(self):
P = self.create_resource(10)
conn = Connection('memory://')
chan = conn.default_channel
assert P.prepare(chan) is chan