mirror of https://github.com/celery/kombu.git
336 lines
11 KiB
Python
336 lines
11 KiB
Python
from __future__ import annotations
|
|
|
|
from unittest.mock import Mock, patch
|
|
|
|
import pytest
|
|
|
|
from kombu import Connection, Exchange, Queue, compat
|
|
from t.mocks import Channel, Transport
|
|
|
|
|
|
class test_misc:
|
|
|
|
def test_iterconsume(self):
|
|
|
|
class MyConnection:
|
|
drained = 0
|
|
|
|
def drain_events(self, *args, **kwargs):
|
|
self.drained += 1
|
|
return self.drained
|
|
|
|
class Consumer:
|
|
active = False
|
|
|
|
def consume(self, *args, **kwargs):
|
|
self.active = True
|
|
|
|
conn = MyConnection()
|
|
consumer = Consumer()
|
|
it = compat._iterconsume(conn, consumer)
|
|
assert next(it) == 1
|
|
assert consumer.active
|
|
|
|
it2 = compat._iterconsume(conn, consumer, limit=10)
|
|
assert list(it2), [2, 3, 4, 5, 6, 7, 8, 9, 10 == 11]
|
|
|
|
def test_Queue_from_dict(self):
|
|
defs = {'binding_key': 'foo.#',
|
|
'exchange': 'fooex',
|
|
'exchange_type': 'topic',
|
|
'durable': True,
|
|
'auto_delete': False}
|
|
|
|
q1 = Queue.from_dict('foo', **dict(defs))
|
|
assert q1.name == 'foo'
|
|
assert q1.routing_key == 'foo.#'
|
|
assert q1.exchange.name == 'fooex'
|
|
assert q1.exchange.type == 'topic'
|
|
assert q1.durable
|
|
assert q1.exchange.durable
|
|
assert not q1.auto_delete
|
|
assert not q1.exchange.auto_delete
|
|
|
|
q2 = Queue.from_dict('foo', **dict(defs,
|
|
exchange_durable=False))
|
|
assert q2.durable
|
|
assert not q2.exchange.durable
|
|
|
|
q3 = Queue.from_dict('foo', **dict(defs,
|
|
exchange_auto_delete=True))
|
|
assert not q3.auto_delete
|
|
assert q3.exchange.auto_delete
|
|
|
|
q4 = Queue.from_dict('foo', **dict(defs,
|
|
queue_durable=False))
|
|
assert not q4.durable
|
|
assert q4.exchange.durable
|
|
|
|
q5 = Queue.from_dict('foo', **dict(defs,
|
|
queue_auto_delete=True))
|
|
assert q5.auto_delete
|
|
assert not q5.exchange.auto_delete
|
|
|
|
assert (Queue.from_dict('foo', **dict(defs)) ==
|
|
Queue.from_dict('foo', **dict(defs)))
|
|
|
|
|
|
class test_Publisher:
|
|
|
|
def setup(self):
|
|
self.connection = Connection(transport=Transport)
|
|
|
|
def test_constructor(self):
|
|
pub = compat.Publisher(self.connection,
|
|
exchange='test_Publisher_constructor',
|
|
routing_key='rkey')
|
|
assert isinstance(pub.backend, Channel)
|
|
assert pub.exchange.name == 'test_Publisher_constructor'
|
|
assert pub.exchange.durable
|
|
assert not pub.exchange.auto_delete
|
|
assert pub.exchange.type == 'direct'
|
|
|
|
pub2 = compat.Publisher(self.connection,
|
|
exchange='test_Publisher_constructor2',
|
|
routing_key='rkey',
|
|
auto_delete=True,
|
|
durable=False)
|
|
assert pub2.exchange.auto_delete
|
|
assert not pub2.exchange.durable
|
|
|
|
explicit = Exchange('test_Publisher_constructor_explicit',
|
|
type='topic')
|
|
pub3 = compat.Publisher(self.connection,
|
|
exchange=explicit)
|
|
assert pub3.exchange == explicit
|
|
|
|
compat.Publisher(self.connection,
|
|
exchange='test_Publisher_constructor3',
|
|
channel=self.connection.default_channel)
|
|
|
|
def test_send(self):
|
|
pub = compat.Publisher(self.connection,
|
|
exchange='test_Publisher_send',
|
|
routing_key='rkey')
|
|
pub.send({'foo': 'bar'})
|
|
assert 'basic_publish' in pub.backend
|
|
pub.close()
|
|
|
|
def test__enter__exit__(self):
|
|
pub = compat.Publisher(
|
|
self.connection,
|
|
exchange='test_Publisher_send',
|
|
routing_key='rkey'
|
|
)
|
|
with pub as x:
|
|
assert x is pub
|
|
|
|
assert pub._closed
|
|
|
|
|
|
class test_Consumer:
|
|
|
|
def setup(self):
|
|
self.connection = Connection(transport=Transport)
|
|
|
|
@patch('kombu.compat._iterconsume')
|
|
def test_iterconsume_calls__iterconsume(self, it, n='test_iterconsume'):
|
|
c = compat.Consumer(self.connection, queue=n, exchange=n)
|
|
c.iterconsume(limit=10, no_ack=True)
|
|
it.assert_called_with(c.connection, c, True, 10)
|
|
|
|
def test_constructor(self, n='test_Consumer_constructor'):
|
|
c = compat.Consumer(self.connection, queue=n, exchange=n,
|
|
routing_key='rkey')
|
|
assert isinstance(c.backend, Channel)
|
|
q = c.queues[0]
|
|
assert q.durable
|
|
assert q.exchange.durable
|
|
assert not q.auto_delete
|
|
assert not q.exchange.auto_delete
|
|
assert q.name == n
|
|
assert q.exchange.name == n
|
|
|
|
c2 = compat.Consumer(self.connection, queue=n + '2',
|
|
exchange=n + '2',
|
|
routing_key='rkey', durable=False,
|
|
auto_delete=True, exclusive=True)
|
|
q2 = c2.queues[0]
|
|
assert not q2.durable
|
|
assert not q2.exchange.durable
|
|
assert q2.auto_delete
|
|
assert q2.exchange.auto_delete
|
|
|
|
def test__enter__exit__(self, n='test__enter__exit__'):
|
|
c = compat.Consumer(
|
|
self.connection,
|
|
queue=n,
|
|
exchange=n,
|
|
routing_key='rkey'
|
|
)
|
|
with c as x:
|
|
assert x is c
|
|
assert c._closed
|
|
|
|
def test_revive(self, n='test_revive'):
|
|
c = compat.Consumer(self.connection, queue=n, exchange=n)
|
|
|
|
with self.connection.channel() as c2:
|
|
c.revive(c2)
|
|
assert c.backend is c2
|
|
|
|
def test__iter__(self, n='test__iter__'):
|
|
c = compat.Consumer(self.connection, queue=n, exchange=n)
|
|
c.iterqueue = Mock()
|
|
|
|
c.__iter__()
|
|
c.iterqueue.assert_called_with(infinite=True)
|
|
|
|
def test_iter(self, n='test_iterqueue'):
|
|
c = compat.Consumer(self.connection, queue=n, exchange=n,
|
|
routing_key='rkey')
|
|
c.close()
|
|
|
|
def test_process_next(self, n='test_process_next'):
|
|
c = compat.Consumer(self.connection, queue=n, exchange=n,
|
|
routing_key='rkey')
|
|
with pytest.raises(NotImplementedError):
|
|
c.process_next()
|
|
c.close()
|
|
|
|
def test_iterconsume(self, n='test_iterconsume'):
|
|
c = compat.Consumer(self.connection, queue=n, exchange=n,
|
|
routing_key='rkey')
|
|
c.close()
|
|
|
|
def test_discard_all(self, n='test_discard_all'):
|
|
c = compat.Consumer(self.connection, queue=n, exchange=n,
|
|
routing_key='rkey')
|
|
c.discard_all()
|
|
assert 'queue_purge' in c.backend
|
|
|
|
def test_fetch(self, n='test_fetch'):
|
|
c = compat.Consumer(self.connection, queue=n, exchange=n,
|
|
routing_key='rkey')
|
|
assert c.fetch() is None
|
|
assert c.fetch(no_ack=True) is None
|
|
assert 'basic_get' in c.backend
|
|
|
|
callback_called = [False]
|
|
|
|
def receive(payload, message):
|
|
callback_called[0] = True
|
|
|
|
c.backend.to_deliver.append('42')
|
|
payload = c.fetch().payload
|
|
assert payload == '42'
|
|
c.backend.to_deliver.append('46')
|
|
c.register_callback(receive)
|
|
assert c.fetch(enable_callbacks=True).payload == '46'
|
|
assert callback_called[0]
|
|
|
|
def test_discard_all_filterfunc_not_supported(self, n='xjf21j21'):
|
|
c = compat.Consumer(self.connection, queue=n, exchange=n,
|
|
routing_key='rkey')
|
|
with pytest.raises(NotImplementedError):
|
|
c.discard_all(filterfunc=lambda x: x)
|
|
c.close()
|
|
|
|
def test_wait(self, n='test_wait'):
|
|
|
|
class C(compat.Consumer):
|
|
|
|
def iterconsume(self, limit=None):
|
|
yield from range(limit)
|
|
|
|
c = C(self.connection,
|
|
queue=n, exchange=n, routing_key='rkey')
|
|
assert c.wait(10) == list(range(10))
|
|
c.close()
|
|
|
|
def test_iterqueue(self, n='test_iterqueue'):
|
|
i = [0]
|
|
|
|
class C(compat.Consumer):
|
|
|
|
def fetch(self, limit=None):
|
|
z = i[0]
|
|
i[0] += 1
|
|
return z
|
|
|
|
c = C(self.connection,
|
|
queue=n, exchange=n, routing_key='rkey')
|
|
assert list(c.iterqueue(limit=10)) == list(range(10))
|
|
c.close()
|
|
|
|
|
|
class test_ConsumerSet:
|
|
|
|
def setup(self):
|
|
self.connection = Connection(transport=Transport)
|
|
|
|
def test_providing_channel(self):
|
|
chan = Mock(name='channel')
|
|
cs = compat.ConsumerSet(self.connection, channel=chan)
|
|
assert cs._provided_channel
|
|
assert cs.backend is chan
|
|
|
|
cs.cancel = Mock(name='cancel')
|
|
cs.close()
|
|
chan.close.assert_not_called()
|
|
|
|
@patch('kombu.compat._iterconsume')
|
|
def test_iterconsume(self, _iterconsume, n='test_iterconsume'):
|
|
c = compat.Consumer(self.connection, queue=n, exchange=n)
|
|
cs = compat.ConsumerSet(self.connection, consumers=[c])
|
|
cs.iterconsume(limit=10, no_ack=True)
|
|
_iterconsume.assert_called_with(c.connection, cs, True, 10)
|
|
|
|
def test_revive(self, n='test_revive'):
|
|
c = compat.Consumer(self.connection, queue=n, exchange=n)
|
|
cs = compat.ConsumerSet(self.connection, consumers=[c])
|
|
|
|
with self.connection.channel() as c2:
|
|
cs.revive(c2)
|
|
assert cs.backend is c2
|
|
|
|
def test_constructor(self, prefix='0daf8h21'):
|
|
dcon = {'%s.xyx' % prefix: {'exchange': '%s.xyx' % prefix,
|
|
'routing_key': 'xyx'},
|
|
'%s.xyz' % prefix: {'exchange': '%s.xyz' % prefix,
|
|
'routing_key': 'xyz'}}
|
|
consumers = [compat.Consumer(self.connection, queue=prefix + str(i),
|
|
exchange=prefix + str(i))
|
|
for i in range(3)]
|
|
c = compat.ConsumerSet(self.connection, consumers=consumers)
|
|
c2 = compat.ConsumerSet(self.connection, from_dict=dcon)
|
|
|
|
assert len(c.queues) == 3
|
|
assert len(c2.queues) == 2
|
|
|
|
c.add_consumer(compat.Consumer(self.connection,
|
|
queue=prefix + 'xaxxxa',
|
|
exchange=prefix + 'xaxxxa'))
|
|
assert len(c.queues) == 4
|
|
for cq in c.queues:
|
|
assert cq.channel is c.channel
|
|
|
|
c2.add_consumer_from_dict(
|
|
'%s.xxx' % prefix,
|
|
exchange='%s.xxx' % prefix,
|
|
routing_key='xxx',
|
|
)
|
|
assert len(c2.queues) == 3
|
|
for c2q in c2.queues:
|
|
assert c2q.channel is c2.channel
|
|
|
|
c.discard_all()
|
|
assert c.channel.called.count('queue_purge') == 4
|
|
c.consume()
|
|
|
|
c.close()
|
|
c2.close()
|
|
assert 'basic_cancel' in c.channel
|
|
assert 'close' in c.channel
|
|
assert 'close' in c2.channel
|