예제 #1
0
class TestAioStomp(AsyncTestCase):
    async def setUpAsync(self):
        self.stomp = AioStomp("127.0.0.1", 61613)

    @patch("aiostomp.aiostomp.StompProtocol")
    @unittest_run_loop
    async def test_aiostomp_supports_ssl(self, stom_protocol_mock):
        ssl_context = ssl.create_default_context()
        stomp = AioStomp("127.0.0.1", 61613, ssl_context=ssl_context)

        args, kwargs = stom_protocol_mock.call_args

        self.assertTrue("127.0.0.1" in args)
        self.assertTrue(61613 in args)
        self.assertTrue(stomp in args)
        self.assertTrue(kwargs["ssl_context"] == ssl_context)

    @unittest_run_loop
    async def test_can_connect_to_server(self):
        self.stomp._protocol.connect = CoroutineMock()
        await self.stomp.connect()

        self.stomp._protocol.connect.assert_called_once()
        self.assertTrue(self.stomp._connected)

    @unittest_run_loop
    async def test_can_reconnect_to_server(self):
        self.stomp._protocol.connect = CoroutineMock()
        self.stomp._protocol.connect.side_effect = [OSError(), True]

        await self.stomp.connect()

        self.assertEqual(self.stomp._protocol.connect.call_count, 2)

    @unittest_run_loop
    async def test_can_reconnect_to_server_with_max_attemps(self):
        self.stomp._reconnect_max_attempts = 2
        self.stomp._protocol.connect = CoroutineMock()
        self.stomp._protocol.connect.side_effect = [OSError(), True]

        await self.stomp.connect()

        self.assertEqual(self.stomp._protocol.connect.call_count, 2)

    @unittest_run_loop
    async def test_reconnection(self):
        self.stomp._protocol.connect = CoroutineMock()

        await self.stomp._reconnect()

        self.stomp._protocol.connect.assert_called_once()

    @patch("aiostomp.aiostomp.logger")
    @unittest_run_loop
    async def test_reconnection_error(self, logger_mock):
        self.stomp._reconnect_max_attempts = 1
        self.stomp._reconnect_attempts = 1

        self.stomp._protocol.connect = CoroutineMock()
        self.stomp._protocol.connect.side_effect = OSError()

        self.stomp._on_error = CoroutineMock()

        await self.stomp._reconnect()

        logger_mock.error.assert_called_with(
            "All connections attempts failed.")
        self.assertIsInstance(self.stomp._on_error.call_args[0][0],
                              ExceededRetryCount)
        self.assertEqual(self.stomp._on_error.call_args[0][0].ref, self.stomp)

    @unittest_run_loop
    async def test_can_reconnect_on_connection_lost(self):
        self.stomp._reconnect = CoroutineMock()

        self.stomp.connection_lost(Exception())

        self.stomp._reconnect.assert_called_once()

    @unittest_run_loop
    async def test_no_reconnect_on_close(self):
        self.stomp._reconnect = CoroutineMock()

        self.stomp._closed = True

        self.stomp.connection_lost(Exception())

        self.stomp._reconnect.assert_not_called()
        self.stomp._closed = False

    @patch("aiostomp.aiostomp.StompProtocol.close")
    def test_can_close_connection(self, close_mock):
        self.stomp.close()

        close_mock.assert_called_once()

    def test_can_subscribe(self):
        self.stomp._protocol.subscribe = Mock()

        self.stomp.subscribe("/queue/test")

        self.assertEqual(len(self.stomp._subscriptions), 1)
        self.stomp._protocol.subscribe.assert_not_called()

    def test_can_get_subscription(self):
        self.stomp._protocol.subscribe = Mock()

        subscription = self.stomp.subscribe("/queue/test")

        self.assertEqual(len(self.stomp._subscriptions), 1)
        self.stomp._protocol.subscribe.assert_not_called()

        value = self.stomp.get("1")
        self.assertEqual(value, subscription)

    def test_can_subscribe_when_connected(self):
        self.stomp._protocol.subscribe = Mock()
        self.stomp._connected = True

        subscription = self.stomp.subscribe("/queue/test")

        self.assertEqual(len(self.stomp._subscriptions), 1)
        self.stomp._protocol.subscribe.assert_called_with(subscription)

    @unittest_run_loop
    async def test_subscribe_after_connection(self):
        self.stomp._protocol.connect = CoroutineMock()
        self.stomp._protocol.subscribe = Mock()

        self.stomp.subscribe("/queue/test")

        self.assertEqual(len(self.stomp._subscriptions), 1)
        self.stomp._protocol.subscribe.assert_not_called()

        await self.stomp.connect()

        self.assertTrue(self.stomp._connected)
        self.stomp._protocol.subscribe.assert_called_once()

    def test_can_unsubscribe(self):
        self.stomp._protocol.subscribe = Mock()
        self.stomp._protocol.unsubscribe = Mock()
        self.stomp._connected = True

        subscription = self.stomp.subscribe("/queue/test")

        self.assertEqual(len(self.stomp._subscriptions), 1)

        self.stomp.unsubscribe(subscription)

        self.stomp._protocol.unsubscribe.assert_called_with(subscription)
        self.assertEqual(len(self.stomp._subscriptions), 0)

    def test_cannot_unsubscribe_when_not_subcribed(self):
        self.stomp._protocol.subscribe = Mock()
        self.stomp._protocol.unsubscribe = Mock()
        self.stomp._connected = True

        subscription = self.stomp.subscribe("/queue/test")
        subscription.id = 2

        self.assertEqual(len(self.stomp._subscriptions), 1)

        self.stomp.unsubscribe(subscription)

        self.stomp._protocol.unsubscribe.assert_not_called()
        self.assertEqual(len(self.stomp._subscriptions), 1)

    def test_can_send_message_with_body_utf8(self):
        send_mock = Mock()
        self.stomp._protocol.send = send_mock

        self.stomp.send("/topic/test",
                        headers={"my-header": "my-value"},
                        body="my body utf-8 ç")

        send_mock.assert_called_with(
            {
                "destination": "/topic/test",
                "my-header": "my-value",
                "content-length": 16,
            },
            b"my body utf-8 \xc3\xa7",
        )

    def test_can_send_message_with_body_binary(self):
        send_mock = Mock()
        self.stomp._protocol.send = send_mock

        self.stomp.send("/topic/test",
                        headers={"my-header": "my-value"},
                        body=b"\xc3\xa7")

        send_mock.assert_called_with(
            {
                "destination": "/topic/test",
                "my-header": "my-value",
                "content-length": 2,
            },
            b"\xc3\xa7",
        )

    def test_can_send_message_with_body_without_content_length(self):
        send_mock = Mock()
        self.stomp._protocol.send = send_mock

        self.stomp.send(
            "/topic/test",
            headers={"my-header": "my-value"},
            body="my body utf-8 ç",
            send_content_length=False,
        )

        send_mock.assert_called_with(
            {
                "destination": "/topic/test",
                "my-header": "my-value"
            },
            b"my body utf-8 \xc3\xa7",
        )

    def test_can_send_message_without_body(self):
        send_mock = Mock()
        self.stomp._protocol.send = send_mock

        self.stomp.send("/topic/test", headers={"my-header": "my-value"})

        send_mock.assert_called_with(
            {
                "destination": "/topic/test",
                "my-header": "my-value",
                "content-length": 0,
            },
            b"",
        )

    def test_can_ack_a_frame(self):
        self.stomp._protocol.subscribe = Mock()
        self.stomp._protocol.ack = Mock()

        self.stomp.subscribe("/queue/test", auto_ack=False)
        self.assertEqual(len(self.stomp._subscriptions), 1)

        frame = Frame("MESSAGE", {"subscription": "1"}, "data")

        self.stomp.ack(frame)

        self.stomp._protocol.ack.assert_called_with(frame)

    def test_can_nack_a_frame(self):
        self.stomp._protocol.subscribe = Mock()
        self.stomp._protocol.nack = Mock()

        self.stomp.subscribe("/queue/test", auto_ack=False)
        self.assertEqual(len(self.stomp._subscriptions), 1)

        frame = Frame("MESSAGE", {"subscription": "1"}, "data")

        self.stomp.nack(frame)

        self.stomp._protocol.nack.assert_called_with(frame)

    def test_cannot_ack_an_unsubscribed_frame(self):
        self.stomp._protocol.ack = Mock()
        self.assertEqual(len(self.stomp._subscriptions), 0)

        frame = Frame("MESSAGE", {"subscription": "1"}, "data")

        with self.assertLogs() as cm:
            self.stomp.ack(frame)
            self.assertIn("WARNING:aiostomp:Subscription 1 not found",
                          cm.output)
        self.stomp._protocol.ack.assert_not_called()

    def test_cannot_nack_an_unsubscribed_frame(self):
        self.stomp._protocol.nack = Mock()
        self.assertEqual(len(self.stomp._subscriptions), 0)

        frame = Frame("MESSAGE", {"subscription": "1"}, "data")

        with self.assertLogs() as cm:
            self.stomp.nack(frame)
            self.assertIn("WARNING:aiostomp:Subscription 1 not found",
                          cm.output)

        self.stomp._protocol.nack.assert_not_called()

    def test_cannot_ack_an_auto_ack_frame(self):
        self.stomp._protocol.subscribe = Mock()
        self.stomp._protocol.ack = Mock()

        self.stomp.subscribe("/queue/test", auto_ack=True)
        self.assertEqual(len(self.stomp._subscriptions), 1)

        frame = Frame("MESSAGE", {"subscription": "1"}, "data")

        with self.assertLogs() as cm:
            self.stomp.ack(frame)
            self.assertIn(
                "WARNING:aiostomp:Auto ack/nack is enabled. Ignoring call.",
                cm.output)

        self.stomp._protocol.ack.assert_not_called()
예제 #2
0
class TestAioStomp(AsyncTestCase):
    async def setUpAsync(self):
        self.stomp = AioStomp('127.0.0.1', 61613)

    @patch('aiostomp.aiostomp.StompProtocol')
    @unittest_run_loop
    async def test_aiostomp_supports_ssl(self, stom_protocol_mock):
        ssl_context = ssl.create_default_context()
        stomp = AioStomp('127.0.0.1', 61613, ssl_context=ssl_context)

        args, kwargs = stom_protocol_mock.call_args

        self.assertTrue('127.0.0.1' in args)
        self.assertTrue(61613 in args)
        self.assertTrue(stomp in args)
        self.assertTrue(kwargs['ssl_context'] == ssl_context)

    @unittest_run_loop
    async def test_can_connect_to_server(self):
        self.stomp._protocol.connect = CoroutineMock()
        await self.stomp.connect()

        self.stomp._protocol.connect.assert_called_once()
        self.assertTrue(self.stomp._connected)

    @unittest_run_loop
    async def test_can_reconnect_to_server(self):
        self.stomp._protocol.connect = CoroutineMock()
        self.stomp._protocol.connect.side_effect = [OSError(), True]

        await self.stomp.connect()

        self.assertEqual(self.stomp._protocol.connect.call_count, 2)

    @unittest_run_loop
    async def test_can_reconnect_to_server_with_max_attemps(self):
        self.stomp._reconnect_max_attempts = 2
        self.stomp._protocol.connect = CoroutineMock()
        self.stomp._protocol.connect.side_effect = [OSError(), True]

        await self.stomp.connect()

        self.assertEqual(self.stomp._protocol.connect.call_count, 2)

    @unittest_run_loop
    async def test_reconnection(self):
        self.stomp._protocol.connect = CoroutineMock()

        await self.stomp._reconnect()

        self.stomp._protocol.connect.assert_called_once()

    @patch('aiostomp.aiostomp.logger')
    @unittest_run_loop
    async def test_reconnection_error(self, logger_mock):
        self.stomp._reconnect_max_attempts = 1
        self.stomp._reconnect_attempts = 1

        self.stomp._protocol.connect = CoroutineMock()
        self.stomp._protocol.connect.side_effect = OSError()

        self.stomp._on_error = CoroutineMock()

        await self.stomp._reconnect()

        logger_mock.error.assert_called_with(
            'All connections attempts failed.')
        self.assertIsInstance(self.stomp._on_error.call_args[0][0],
                              ExceededRetryCount)
        self.assertEqual(self.stomp._on_error.call_args[0][0].ref, self.stomp)

    @unittest_run_loop
    async def test_can_reconnect_on_connection_lost(self):
        self.stomp._reconnect = CoroutineMock()

        self.stomp.connection_lost(Exception())

        self.stomp._reconnect.assert_called_once()

    @unittest_run_loop
    async def test_no_reconnect_on_close(self):
        self.stomp._reconnect = CoroutineMock()

        self.stomp._closed = True

        self.stomp.connection_lost(Exception())

        self.stomp._reconnect.assert_not_called()
        self.stomp._closed = False

    @patch('aiostomp.aiostomp.StompProtocol.close')
    def test_can_close_connection(self, close_mock):
        self.stomp.close()

        close_mock.assert_called_once()

    def test_can_subscribe(self):
        self.stomp._protocol.subscribe = Mock()

        self.stomp.subscribe('/queue/test')

        self.assertEqual(len(self.stomp._subscriptions), 1)
        self.stomp._protocol.subscribe.assert_not_called()

    def test_can_get_subscription(self):
        self.stomp._protocol.subscribe = Mock()

        subscription = self.stomp.subscribe('/queue/test')

        self.assertEqual(len(self.stomp._subscriptions), 1)
        self.stomp._protocol.subscribe.assert_not_called()

        value = self.stomp.get('1')
        self.assertEqual(value, subscription)

    def test_can_subscribe_when_connected(self):
        self.stomp._protocol.subscribe = Mock()
        self.stomp._connected = True

        subscription = self.stomp.subscribe('/queue/test')

        self.assertEqual(len(self.stomp._subscriptions), 1)
        self.stomp._protocol.subscribe.assert_called_with(subscription)

    @unittest_run_loop
    async def test_subscribe_after_connection(self):
        self.stomp._protocol.connect = CoroutineMock()
        self.stomp._protocol.subscribe = Mock()

        self.stomp.subscribe('/queue/test')

        self.assertEqual(len(self.stomp._subscriptions), 1)
        self.stomp._protocol.subscribe.assert_not_called()

        await self.stomp.connect()

        self.assertTrue(self.stomp._connected)
        self.stomp._protocol.subscribe.assert_called_once()

    def test_can_unsubscribe(self):
        self.stomp._protocol.subscribe = Mock()
        self.stomp._protocol.unsubscribe = Mock()
        self.stomp._connected = True

        subscription = self.stomp.subscribe('/queue/test')

        self.assertEqual(len(self.stomp._subscriptions), 1)

        self.stomp.unsubscribe(subscription)

        self.stomp._protocol.unsubscribe.assert_called_with(subscription)
        self.assertEqual(len(self.stomp._subscriptions), 0)

    def test_cannot_unsubscribe_when_not_subcribed(self):
        self.stomp._protocol.subscribe = Mock()
        self.stomp._protocol.unsubscribe = Mock()
        self.stomp._connected = True

        subscription = self.stomp.subscribe('/queue/test')
        subscription.id = 2

        self.assertEqual(len(self.stomp._subscriptions), 1)

        self.stomp.unsubscribe(subscription)

        self.stomp._protocol.unsubscribe.assert_not_called()
        self.assertEqual(len(self.stomp._subscriptions), 1)

    def test_can_send_message_with_body_utf8(self):
        send_mock = Mock()
        self.stomp._protocol.send = send_mock

        self.stomp.send('/topic/test',
                        headers={'my-header': 'my-value'},
                        body='my body utf-8 ç')

        send_mock.assert_called_with(
            {
                'destination': '/topic/test',
                'my-header': 'my-value',
                'content-length': 16,
            },
            b'my body utf-8 \xc3\xa7',
        )

    def test_can_send_message_with_body_binary(self):
        send_mock = Mock()
        self.stomp._protocol.send = send_mock

        self.stomp.send('/topic/test',
                        headers={'my-header': 'my-value'},
                        body=b'\xc3\xa7')

        send_mock.assert_called_with(
            {
                'destination': '/topic/test',
                'my-header': 'my-value',
                'content-length': 2,
            },
            b'\xc3\xa7',
        )

    def test_can_send_message_with_body_without_content_length(self):
        send_mock = Mock()
        self.stomp._protocol.send = send_mock

        self.stomp.send(
            '/topic/test',
            headers={'my-header': 'my-value'},
            body='my body utf-8 ç',
            send_content_length=False,
        )

        send_mock.assert_called_with(
            {
                'destination': '/topic/test',
                'my-header': 'my-value'
            },
            b'my body utf-8 \xc3\xa7',
        )

    def test_can_send_message_without_body(self):
        send_mock = Mock()
        self.stomp._protocol.send = send_mock

        self.stomp.send('/topic/test', headers={'my-header': 'my-value'})

        send_mock.assert_called_with(
            {
                'destination': '/topic/test',
                'my-header': 'my-value',
                'content-length': 0
            }, b'')

    def test_can_ack_a_frame(self):
        self.stomp._protocol.subscribe = Mock()
        self.stomp._protocol.ack = Mock()

        self.stomp.subscribe('/queue/test', auto_ack=False)
        self.assertEqual(len(self.stomp._subscriptions), 1)

        frame = Frame('MESSAGE', {'subscription': '1'}, 'data')

        self.stomp.ack(frame)

        self.stomp._protocol.ack.assert_called_with(frame)

    def test_can_nack_a_frame(self):
        self.stomp._protocol.subscribe = Mock()
        self.stomp._protocol.nack = Mock()

        self.stomp.subscribe('/queue/test', auto_ack=False)
        self.assertEqual(len(self.stomp._subscriptions), 1)

        frame = Frame('MESSAGE', {'subscription': '1'}, 'data')

        self.stomp.nack(frame)

        self.stomp._protocol.nack.assert_called_with(frame)

    def test_cannot_ack_an_unsubscribed_frame(self):
        self.stomp._protocol.ack = Mock()
        self.assertEqual(len(self.stomp._subscriptions), 0)

        frame = Frame('MESSAGE', {'subscription': '1'}, 'data')

        with self.assertLogs() as cm:
            self.stomp.ack(frame)
            self.assertIn('WARNING:aiostomp:Subscription 1 not found',
                          cm.output)
        self.stomp._protocol.ack.assert_not_called()

    def test_cannot_nack_an_unsubscribed_frame(self):
        self.stomp._protocol.nack = Mock()
        self.assertEqual(len(self.stomp._subscriptions), 0)

        frame = Frame('MESSAGE', {'subscription': '1'}, 'data')

        with self.assertLogs() as cm:
            self.stomp.nack(frame)
            self.assertIn('WARNING:aiostomp:Subscription 1 not found',
                          cm.output)

        self.stomp._protocol.nack.assert_not_called()

    def test_cannot_ack_an_auto_ack_frame(self):
        self.stomp._protocol.subscribe = Mock()
        self.stomp._protocol.ack = Mock()

        self.stomp.subscribe('/queue/test', auto_ack=True)
        self.assertEqual(len(self.stomp._subscriptions), 1)

        frame = Frame('MESSAGE', {'subscription': '1'}, 'data')

        with self.assertLogs() as cm:
            self.stomp.ack(frame)
            self.assertIn(
                'WARNING:aiostomp:Auto ack/nack is enabled. Ignoring call.',
                cm.output)

        self.stomp._protocol.ack.assert_not_called()