Пример #1
0
    def setUp(self):
        # patching some global objects and preparing mockups of them
        self._stderr_patcher = rlocked_patch('sys.stderr')
        self.stderr_mock = self._stderr_patcher.start()
        self.addCleanup(self._stderr_patcher.stop)

        # patching some imported modules and preparing mockups of them
        self._time_patcher = rlocked_patch('n6lib.amqp_getters_pushers.time')
        self.time_mock = self._time_patcher.start()
        self.addCleanup(self._time_patcher.stop)

        self._traceback_patcher = rlocked_patch(
            'n6lib.amqp_getters_pushers.traceback')
        self.traceback_mock = self._traceback_patcher.start()
        self.addCleanup(self._traceback_patcher.stop)

        self._pika_patcher = rlocked_patch('n6lib.amqp_getters_pushers.pika')
        self.pika_mock = self._pika_patcher.start()
        self.addCleanup(self._pika_patcher.stop)

        # preparing sentinel exceptions
        class AMQPConnectionError_sentinel_exc(Exception):
            pass

        class ConnectionClosed_sentinel_exc(Exception):
            pass

        class generic_sentinel_exc(Exception):
            pass

        self.AMQPConnectionError_sentinel_exc = AMQPConnectionError_sentinel_exc
        self.ConnectionClosed_sentinel_exc = ConnectionClosed_sentinel_exc
        self.generic_sentinel_exc = generic_sentinel_exc

        # preparing mockups of different objects
        self.conn_mock = RLockedMagicMock()
        self.channel_mock = RLockedMagicMock()
        self.optional_setup_communication_mock = RLockedMagicMock()
        self.serialize = RLockedMagicMock()
        self.error_callback = RLockedMagicMock()

        # configuring the mockups
        self.pika_mock.exceptions.AMQPConnectionError = AMQPConnectionError_sentinel_exc
        self.pika_mock.exceptions.ConnectionClosed = ConnectionClosed_sentinel_exc
        self.pika_mock.ConnectionParameters.return_value = sen.conn_parameters
        self.pika_mock.BlockingConnection.side_effect = [
            AMQPConnectionError_sentinel_exc,
            self.conn_mock,
        ]
        self.pika_mock.BasicProperties.return_value = sen.props
        self.conn_mock.channel.return_value = self.channel_mock
        self.serialize.side_effect = (lambda data: data)
Пример #2
0
    def test_publishing_with_fatal_error(self):
        with rlocked_patch(
                'n6lib.amqp_getters_pushers.AMQPThreadedPusher._publish',
                # not an Exception subclass:
                side_effect=BaseException,
        ) as _publish_mock:
            self._make_obj()
            try:
                self.obj.push(sen.data, sen.rk)

                # we must wait to let the pub. thread operate and crash
                while _publish_mock.call_count < 1:
                    time.sleep(0.01)
                self.obj._publishing_thread.join(15.0)

                self.assertFalse(self.obj._publishing_thread.is_alive())
                self.assertFalse(self.obj._publishing)

                self.assertTrue(self.stderr_mock.mock_calls)
            finally:
                self.obj._publishing_thread.join(15.0)
                if self.obj._publishing_thread.is_alive():
                    raise RuntimeError('unexpected problem: the publishing '
                                       'thread did not terminate :-/')

        self.assertFalse(self.error_callback.mock_calls)
        self.assertFalse(self.traceback_mock.print_exc.mock_calls)
Пример #3
0
    def test_publishing_with_error_callback_raising_exception(self):
        self.error_callback.side_effect = TypeError

        exceptions_from_publish = [
            self.ConnectionClosed_sentinel_exc,
            TypeError,
        ]
        expected_publish_call_count = 2

        with rlocked_patch(
                'n6lib.amqp_getters_pushers.AMQPThreadedPusher._publish',
                side_effect=self._side_effect_for_publish(
                    exceptions_from_publish)) as _publish_mock:
            self._error_case_commons(_publish_mock,
                                     expected_publish_call_count)

        self.assertEqual(_publish_mock.mock_calls, [
            call(sen.data, sen.rk, None),
            call(sen.data, sen.rk, None),
        ])
        self.assertEqual(self.optional_setup_communication_mock.mock_calls,
                         [call()])
        self.assertEqual(self.error_callback.mock_calls, [call(ANY)])
        self.assertEqual(self.traceback_mock.print_exc.mock_calls, [call()])
        self.assertTrue(self.stderr_mock.mock_calls
                        )  # `print(..., file=sys.stderr)` used...

        # the message has not been published
        self.assertFalse(self.pika_mock.BasicProperties.mock_calls)
        self.assertFalse(self.channel_mock.basic_publish.mock_calls)
Пример #4
0
    def test_publishing_with_exceptions_and_no_error_callback(self):
        self.error_callback = None

        exceptions_from_publish = [
            self.ConnectionClosed_sentinel_exc,
            TypeError,
        ]
        expected_publish_call_count = 2

        with rlocked_patch(
                'n6lib.amqp_getters_pushers.AMQPThreadedPusher._publish',
                side_effect=self._side_effect_for_publish(
                    exceptions_from_publish)) as _publish_mock:
            self._error_case_commons(_publish_mock,
                                     expected_publish_call_count)

        assert self.error_callback is None, "bug in test case"

        self.assertIsNone(self.obj._error_callback)
        self.assertEqual(_publish_mock.mock_calls, [
            call(sen.data, sen.rk, None),
            call(sen.data, sen.rk, None),
        ])
        self.assertEqual(self.optional_setup_communication_mock.mock_calls,
                         [call()])
        self.assertEqual(self.traceback_mock.print_exc.mock_calls, [call()])

        # the message has not been published
        self.assertFalse(self.pika_mock.BasicProperties.mock_calls)
        self.assertFalse(self.channel_mock.basic_publish.mock_calls)
Пример #5
0
    def test_publishing_flag_is_False(self):
        # do not try to reconnect on pika.exceptions.ConnectionClosed
        # but continue publishing until the output fifo is empty
        def basic_publish_side_effect(*args, **kwargs):
            time.sleep(0.02)

        self.channel_mock.basic_publish.side_effect = basic_publish_side_effect
        with rlocked_patch(
                'n6lib.amqp_getters_pushers.AMQPThreadedPusher._publish',
                side_effect=self._side_effect_for_publish(exception_seq=[
                    None,
                    self.ConnectionClosed_sentinel_exc,
                    None,
                ]),
        ) as _publish_mock:
            with self._testing_normal_push(error_callback_call_count=1) as obj:
                obj._publishing = False
                obj._output_fifo.put_nowait((sen.data1, sen.rk1, None))
                obj._output_fifo.put_nowait((sen.data_err, sen.rk_err, None))
                obj._output_fifo.put_nowait((sen.data2, sen.rk2, {
                    'custom': sen.custom_value
                }))

        self.assertEqual(_publish_mock.mock_calls, [
            call(sen.data1, sen.rk1, None),
            call(sen.data_err, sen.rk_err, None),
            call(sen.data2, sen.rk2, {'custom': sen.custom_value}),
        ])

        # no reconnections
        self.assertFalse(self.optional_setup_communication_mock.mock_calls)

        # one error callback call
        self.assertEqual(self.error_callback.mock_calls, [call(ANY)])
Пример #6
0
    def test_serialization_error(self):
        self.serialize.side_effect = TypeError
        expected_serialize_call_count = 1
        with rlocked_patch(
                'n6lib.amqp_getters_pushers.AMQPThreadedPusher._publish'
        ) as _publish_mock:
            self._error_case_commons(self.serialize,
                                     expected_serialize_call_count)

        self.assertEqual(self.serialize.mock_calls, [call(sen.data)])
        self.assertEqual(self.error_callback.mock_calls, [call(ANY)])
        self.assertFalse(self.traceback_mock.print_exc.mock_calls)
        self.assertFalse(self.stderr_mock.mock_calls)
        self.assertFalse(self.optional_setup_communication_mock.mock_calls)

        # the message has not been published
        self.assertFalse(_publish_mock.mock_calls)
        self.assertFalse(self.pika_mock.BasicProperties.mock_calls)
        self.assertFalse(self.channel_mock.basic_publish.mock_calls)
Пример #7
0
    def test_publishing_with_one_ConnectionClosed(self):
        exceptions_from_publish = [
            self.ConnectionClosed_sentinel_exc,
            None,
        ]
        expected_publish_call_count = 2

        with rlocked_patch(
                'n6lib.amqp_getters_pushers.AMQPThreadedPusher._publish',
                side_effect=self._side_effect_for_publish(
                    exceptions_from_publish)) as _publish_mock:
            self._error_case_commons(_publish_mock,
                                     expected_publish_call_count)

        self.assertEqual(self.optional_setup_communication_mock.mock_calls,
                         [call()])
        self.assertEqual(_publish_mock.mock_calls, [
            call(sen.data, sen.rk, None),
            call(sen.data, sen.rk, None),
        ])
        self.assertFalse(self.error_callback.mock_calls)
        self.assertFalse(self.traceback_mock.print_exc.mock_calls)
        self.assertFalse(self.stderr_mock.mock_calls)

        # properties of the published message have been created properly...
        self.assertEqual(self.pika_mock.BasicProperties.mock_calls, [
            call(prop_kwarg=sen.prop_value),
        ])
        # ...and the message has been published properly
        self.assertEqual(self.channel_mock.basic_publish.mock_calls, [
            call(
                exchange=sen.exchange,
                routing_key=sen.rk,
                body=sen.data,
                properties=sen.props,
                mandatory=sen.mandatory,
            ),
        ])
Пример #8
0
 def test__init__specifying_all_and_obtaining_global_conn_params__with_ssl(
         self):
     connection_params_dict_mock = RLockedMagicMock(
         name='connection_params_dict')
     connection_params_dict_mock.get.return_value = True
     connection_params_dict_mock.__contains__.return_value = True
     with rlocked_patch(
             'n6lib.amqp_getters_pushers.get_amqp_connection_params_dict',
             **{'return_value':
                connection_params_dict_mock}) as get_amqp_conn_params_mock:
         self.meth.__init__(connection_params_dict=None,
                            exchange={
                                'exchange': sen.exchange,
                                'bar': sen.bar
                            },
                            queues_to_declare=[
                                sen.queue1,
                                {
                                    'blabla': sen.blabla
                                },
                                {
                                    'blabla': sen.blabla,
                                    'callback': sen.callback
                                },
                            ],
                            serialize=sen.serialize,
                            prop_kwargs=sen.prop_kwargs,
                            mandatory=sen.mandatory,
                            output_fifo_max_size=54321,
                            error_callback=sen.error_callback)
     # attrs
     self.assertIs(self.mock._connection_params_dict,
                   connection_params_dict_mock)
     self.assertEqual(self.mock._exchange, {
         'exchange': sen.exchange,
         'bar': sen.bar
     })
     self.assertEqual(self.mock._exchange_name, sen.exchange)
     self.assertEqual(self.mock._queues_to_declare, [
         {
             'queue': sen.queue1,
             'callback': ANY
         },
         {
             'blabla': sen.blabla,
             'callback': ANY
         },
         {
             'blabla': sen.blabla,
             'callback': sen.callback
         },
     ])
     self.assertEqual(self.mock._serialize, sen.serialize)
     self.assertEqual(self.mock._prop_kwargs, sen.prop_kwargs)
     self.assertEqual(self.mock._mandatory, sen.mandatory)
     self.assertIs(self.mock._output_fifo.__class__, queue.Queue)
     self.assertEqual(self.mock._output_fifo.maxsize, 54321)
     self.assertEqual(self.mock._error_callback, sen.error_callback)
     # calls
     self.assertEqual(self.mock.mock_calls, [
         call._setup_communication(),
         call._start_publishing(),
     ])
     self.assertEqual(get_amqp_conn_params_mock.mock_calls, [
         call(),
     ])
     self.assertEqual(
         connection_params_dict_mock.mock_calls,
         [
             call.get('ssl'),
             call.setdefault('credentials', ANY),
             ('__contains__', ('client_properties', ),
              {}),  # because cannot use `call.__contains__`
         ])
     self.assertIsInstance(
         connection_params_dict_mock.setdefault.mock_calls[0][-2]
         [1],  # 2nd arg for setdefault
         pika.credentials.ExternalCredentials)