2018-05-16 03:24:45 +02:00
|
|
|
from typing import Any, Dict
|
2020-06-11 00:54:34 +02:00
|
|
|
from unittest import mock
|
2018-03-20 03:06:19 +01:00
|
|
|
|
2018-05-16 02:39:29 +02:00
|
|
|
from django.test import override_settings
|
2020-06-11 00:54:34 +02:00
|
|
|
from pika.exceptions import AMQPConnectionError, ConnectionClosed
|
2018-03-20 03:06:19 +01:00
|
|
|
|
2020-06-11 00:54:34 +02:00
|
|
|
from zerver.lib.queue import TornadoQueueClient, get_queue_client, queue_json_publish
|
2018-03-20 03:06:19 +01:00
|
|
|
from zerver.lib.test_classes import ZulipTestCase
|
|
|
|
|
2020-06-11 00:54:34 +02:00
|
|
|
|
2018-03-20 03:06:19 +01:00
|
|
|
class TestTornadoQueueClient(ZulipTestCase):
|
|
|
|
@mock.patch('zerver.lib.queue.logging.getLogger', autospec=True)
|
|
|
|
@mock.patch('zerver.lib.queue.ExceptionFreeTornadoConnection', autospec=True)
|
|
|
|
def test_on_open_closed(self, mock_cxn: mock.MagicMock,
|
|
|
|
mock_get_logger: mock.MagicMock) -> None:
|
|
|
|
connection = TornadoQueueClient()
|
2019-10-09 04:38:43 +02:00
|
|
|
connection.connection.channel.side_effect = ConnectionClosed('500', 'test')
|
2018-03-20 03:06:19 +01:00
|
|
|
connection._on_open(mock.MagicMock())
|
2018-05-16 02:39:29 +02:00
|
|
|
|
|
|
|
|
|
|
|
class TestQueueImplementation(ZulipTestCase):
|
|
|
|
@override_settings(USING_RABBITMQ=True)
|
|
|
|
def test_queue_basics(self) -> None:
|
|
|
|
queue_client = get_queue_client()
|
2020-06-06 04:22:15 +02:00
|
|
|
queue_client.publish("test_suite", b"test_event\x00\xff")
|
2018-05-16 02:39:29 +02:00
|
|
|
|
|
|
|
result = queue_client.drain_queue("test_suite")
|
2020-06-06 04:22:15 +02:00
|
|
|
self.assertEqual(result, [b"test_event\x00\xff"])
|
2018-05-16 02:39:29 +02:00
|
|
|
|
|
|
|
@override_settings(USING_RABBITMQ=True)
|
|
|
|
def test_queue_basics_json(self) -> None:
|
|
|
|
queue_json_publish("test_suite", {"event": "my_event"})
|
|
|
|
|
|
|
|
queue_client = get_queue_client()
|
2020-06-06 04:22:15 +02:00
|
|
|
result = queue_client.json_drain_queue("test_suite")
|
2018-05-16 02:39:29 +02:00
|
|
|
self.assertEqual(len(result), 1)
|
|
|
|
self.assertEqual(result[0]['event'], 'my_event')
|
2018-05-16 03:24:45 +02:00
|
|
|
|
|
|
|
@override_settings(USING_RABBITMQ=True)
|
|
|
|
def test_register_consumer(self) -> None:
|
|
|
|
output = []
|
|
|
|
|
|
|
|
queue_client = get_queue_client()
|
|
|
|
|
|
|
|
def collect(event: Dict[str, Any]) -> None:
|
|
|
|
output.append(event)
|
|
|
|
queue_client.stop_consuming()
|
|
|
|
|
|
|
|
queue_client.register_json_consumer("test_suite", collect)
|
|
|
|
queue_json_publish("test_suite", {"event": "my_event"})
|
|
|
|
|
|
|
|
queue_client.start_consuming()
|
|
|
|
|
|
|
|
self.assertEqual(len(output), 1)
|
|
|
|
self.assertEqual(output[0]['event'], 'my_event')
|
|
|
|
|
|
|
|
@override_settings(USING_RABBITMQ=True)
|
|
|
|
def test_register_consumer_nack(self) -> None:
|
|
|
|
output = []
|
|
|
|
count = 0
|
|
|
|
|
|
|
|
queue_client = get_queue_client()
|
|
|
|
|
|
|
|
def collect(event: Dict[str, Any]) -> None:
|
|
|
|
queue_client.stop_consuming()
|
|
|
|
nonlocal count
|
|
|
|
count += 1
|
|
|
|
if count == 1:
|
|
|
|
raise Exception("Make me nack!")
|
|
|
|
output.append(event)
|
|
|
|
|
|
|
|
queue_client.register_json_consumer("test_suite", collect)
|
|
|
|
queue_json_publish("test_suite", {"event": "my_event"})
|
|
|
|
|
|
|
|
try:
|
|
|
|
queue_client.start_consuming()
|
2018-05-24 16:41:34 +02:00
|
|
|
except Exception:
|
2018-05-16 03:24:45 +02:00
|
|
|
queue_client.register_json_consumer("test_suite", collect)
|
|
|
|
queue_client.start_consuming()
|
|
|
|
|
|
|
|
# Confirm that we processed the event fully once
|
|
|
|
self.assertEqual(count, 2)
|
|
|
|
self.assertEqual(len(output), 1)
|
|
|
|
self.assertEqual(output[0]['event'], 'my_event')
|
2018-05-16 02:39:29 +02:00
|
|
|
|
|
|
|
@override_settings(USING_RABBITMQ=True)
|
|
|
|
def test_queue_error_json(self) -> None:
|
|
|
|
queue_client = get_queue_client()
|
|
|
|
actual_publish = queue_client.publish
|
|
|
|
|
|
|
|
self.counter = 0
|
|
|
|
|
|
|
|
def throw_connection_error_once(self_obj: Any, *args: Any,
|
|
|
|
**kwargs: Any) -> None:
|
|
|
|
self.counter += 1
|
|
|
|
if self.counter <= 1:
|
|
|
|
raise AMQPConnectionError("test")
|
|
|
|
actual_publish(*args, **kwargs)
|
|
|
|
|
|
|
|
with mock.patch("zerver.lib.queue.SimpleQueueClient.publish",
|
2020-07-26 14:22:00 +02:00
|
|
|
throw_connection_error_once), self.assertLogs('zulip.queue', level='WARN') as warn_logs:
|
2018-05-16 02:39:29 +02:00
|
|
|
queue_json_publish("test_suite", {"event": "my_event"})
|
2020-07-26 14:22:00 +02:00
|
|
|
self.assertEqual(warn_logs.output, [
|
|
|
|
'WARNING:zulip.queue:Failed to send to rabbitmq, trying to reconnect and send again'
|
|
|
|
])
|
2018-05-16 02:39:29 +02:00
|
|
|
|
2020-06-06 04:22:15 +02:00
|
|
|
result = queue_client.json_drain_queue("test_suite")
|
2018-05-16 02:39:29 +02:00
|
|
|
self.assertEqual(len(result), 1)
|
|
|
|
self.assertEqual(result[0]['event'], 'my_event')
|
|
|
|
|
|
|
|
@override_settings(USING_RABBITMQ=True)
|
|
|
|
def tearDown(self) -> None:
|
|
|
|
queue_client = get_queue_client()
|
|
|
|
queue_client.drain_queue("test_suite")
|
2019-10-18 16:11:48 +02:00
|
|
|
super().tearDown()
|