Beispiel #1
0
 def test_setup_sync(self):
     """
     ApplicationHelper.setup() should return ``None``, not a Deferred.
     """
     msg_helper = ApplicationHelper(None)
     self.add_cleanup(msg_helper.cleanup)
     self.assertEqual(msg_helper.setup(), None)
Beispiel #2
0
 def test_setup_sync(self):
     """
     ApplicationHelper.setup() should return ``None``, not a Deferred.
     """
     msg_helper = ApplicationHelper(None)
     self.add_cleanup(msg_helper.cleanup)
     self.assertEqual(msg_helper.setup(), None)
    def get_worker(self, config=None):
        """Get a new MessageForwardingWorker with the provided config"""
        if config is None:
            config = {}

        app_helper = ApplicationHelper(MessageForwardingWorker)
        yield app_helper.setup()
        self.addCleanup(app_helper.cleanup)

        persistencehelper = PersistenceHelper()
        yield persistencehelper.setup()
        self.addCleanup(persistencehelper.cleanup)

        config = conjoin(
            persistencehelper.mk_config(
                {
                    "transport_name": "testtransport",
                    "mo_message_url": self.url.decode("utf-8"),
                    "inbound_ttl": 60,
                    "outbound_ttl": 60 * 60 * 24 * 2,
                }
            ),
            config,
        )

        worker = yield app_helper.get_application(config)
        returnValue(worker)
Beispiel #4
0
    def get_worker(self, config=None):
        '''Get a new MessageForwardingWorker with the provided config'''
        if config is None:
            config = {}

        self.app_helper = ApplicationHelper(MessageForwardingWorker)
        yield self.app_helper.setup()
        self.addCleanup(self.app_helper.cleanup)

        persistencehelper = PersistenceHelper()
        yield persistencehelper.setup()
        self.addCleanup(persistencehelper.cleanup)

        config = conjoin(
            persistencehelper.mk_config({
                'transport_name':
                'testtransport',
                'mo_message_url':
                self.url.decode('utf-8'),
                'inbound_ttl':
                60,
                'outbound_ttl':
                60 * 60 * 24 * 2,
                'metric_window':
                1.0,
            }), config)

        worker = yield self.app_helper.get_application(config)
        returnValue(worker)
Beispiel #5
0
 def test_cleanup(self):
     """
     ApplicationHelper.cleanup() should call .cleanup() on its
     PersistenceHelper and WorkerHelper.
     """
     app_helper = ApplicationHelper(None)
     app_helper.persistence_helper = FakeCleanupCheckHelper()
     app_helper.worker_helper = FakeCleanupCheckHelper()
     self.assertEqual(app_helper.persistence_helper.cleaned_up, False)
     self.assertEqual(app_helper.worker_helper.cleaned_up, False)
     success_result_of(app_helper.cleanup())
     self.assertEqual(app_helper.persistence_helper.cleaned_up, True)
     self.assertEqual(app_helper.worker_helper.cleaned_up, True)
Beispiel #6
0
 def test_cleanup(self):
     """
     ApplicationHelper.cleanup() should call .cleanup() on its
     PersistenceHelper and WorkerHelper.
     """
     app_helper = ApplicationHelper(None)
     app_helper.persistence_helper = FakeCleanupCheckHelper()
     app_helper.worker_helper = FakeCleanupCheckHelper()
     self.assertEqual(app_helper.persistence_helper.cleaned_up, False)
     self.assertEqual(app_helper.worker_helper.cleaned_up, False)
     success_result_of(app_helper.cleanup())
     self.assertEqual(app_helper.persistence_helper.cleaned_up, True)
     self.assertEqual(app_helper.worker_helper.cleaned_up, True)
Beispiel #7
0
 def test_get_application_different_class(self):
     """
     .get_application() should return an instance of the specified worker
     class if one is provided.
     """
     app_helper = self.add_helper(ApplicationHelper(ApplicationWorker))
     app = yield app_helper.get_application({}, cls=RunningCheckApplication)
     self.assertIsInstance(app, RunningCheckApplication)
Beispiel #8
0
 def test_get_application_defaults(self):
     """
     .get_application() should return a started application worker.
     """
     app_helper = self.add_helper(
         ApplicationHelper(RunningCheckApplication))
     app = yield app_helper.get_application({})
     self.assertIsInstance(app, RunningCheckApplication)
     self.assertEqual(app.app_worker_running, True)
Beispiel #9
0
    def get_worker(self, config=None):
        '''Get a new ChannelStatusWorker with the provided config'''
        if config is None:
            config = {}

        app_helper = ApplicationHelper(ChannelStatusWorker)
        yield app_helper.setup()
        self.addCleanup(app_helper.cleanup)

        persistencehelper = PersistenceHelper()
        yield persistencehelper.setup()
        self.addCleanup(persistencehelper.cleanup)

        config = conjoin(persistencehelper.mk_config({
            'channel_id': 'testchannel',
        }), config)

        worker = yield app_helper.get_application(config)
        returnValue(worker)
Beispiel #10
0
    def get_worker(self, config=None):
        '''Get a new ChannelStatusWorker with the provided config'''
        if config is None:
            config = {}

        app_helper = ApplicationHelper(ChannelStatusWorker)
        yield app_helper.setup()
        self.addCleanup(app_helper.cleanup)

        persistencehelper = PersistenceHelper()
        yield persistencehelper.setup()
        self.addCleanup(persistencehelper.cleanup)

        config = conjoin(persistencehelper.mk_config({
            'channel_id': 'testchannel',
        }), config)

        worker = yield app_helper.get_application(config)
        returnValue(worker)
Beispiel #11
0
 def test_get_application_no_start(self):
     """
     .get_application() should return an unstarted application worker if
     passed ``start=False``.
     """
     app_helper = self.add_helper(
         ApplicationHelper(RunningCheckApplication))
     app = yield app_helper.get_application({}, start=False)
     self.assertIsInstance(app, RunningCheckApplication)
     self.assertEqual(app.app_worker_running, False)
Beispiel #12
0
 def test_all_params(self):
     """
     ApplicationHelper should pass use_riak to its PersistenceHelper and all
     other params to its MessageHelper.
     """
     fake_app_class = object()
     app_helper = ApplicationHelper(fake_app_class,
                                    use_riak=True,
                                    transport_addr='Obs station')
     self.assertEqual(app_helper.persistence_helper.use_riak, True)
     self.assertEqual(app_helper.msg_helper.transport_addr, 'Obs station')
Beispiel #13
0
 def setUp(self):
     self.app_helper = self.add_helper(
         ApplicationHelper(DummyApplicationWorker))
     self.worker = yield self.app_helper.get_application({
         'send_to': {
             'default': {
                 'transport_name': 'default_transport',
             },
             'outbound1': {
                 'transport_name': 'outbound1_transport',
             },
         },
     })
Beispiel #14
0
 def test_defaults(self):
     """
     ApplicationHelper instances should have the expected parameter
     defaults.
     """
     fake_app_class = object()
     app_helper = ApplicationHelper(fake_app_class)
     self.assertEqual(app_helper.application_class, fake_app_class)
     self.assertIsInstance(app_helper.persistence_helper, PersistenceHelper)
     self.assertIsInstance(app_helper.msg_helper, MessageHelper)
     self.assertIsInstance(app_helper.worker_helper, WorkerHelper)
     dispatch_helper = app_helper.dispatch_helper
     self.assertIsInstance(dispatch_helper, MessageDispatchHelper)
     self.assertEqual(dispatch_helper.msg_helper, app_helper.msg_helper)
     self.assertEqual(dispatch_helper.worker_helper,
                      app_helper.worker_helper)
     self.assertEqual(app_helper.persistence_helper.use_riak, False)
Beispiel #15
0
    def setUp(self):
        root = Resource()
        # data is elephant with a UTF-8 encoded BOM
        # it is a sad elephant (as seen in the wild)
        root.putChild("word", Data('\xef\xbb\xbfelephant\r\n', 'text/html'))
        site_factory = Site(root)
        self.webserver = yield reactor.listenTCP(0,
                                                 site_factory,
                                                 interface='127.0.0.1')
        self.add_cleanup(self.webserver.loseConnection)
        addr = self.webserver.getHost()
        random_word_url = "http://%s:%s/word" % (addr.host, addr.port)

        self.app_helper = self.add_helper(ApplicationHelper(HangmanWorker))

        self.worker = yield self.app_helper.get_application({
            'worker_name':
            'test_hangman',
            'random_word_url':
            random_word_url,
        })
        yield self.worker.session_manager.redis._purge_all()  # just in case
Beispiel #16
0
    def get_worker(self, config=None):
        '''Get a new MessageForwardingWorker with the provided config'''
        if config is None:
            config = {}

        self.app_helper = ApplicationHelper(MessageForwardingWorker)
        yield self.app_helper.setup()
        self.addCleanup(self.app_helper.cleanup)

        persistencehelper = PersistenceHelper()
        yield persistencehelper.setup()
        self.addCleanup(persistencehelper.cleanup)

        config = conjoin(persistencehelper.mk_config({
            'transport_name': 'testtransport',
            'mo_message_url': self.url.decode('utf-8'),
            'inbound_ttl': 60,
            'outbound_ttl': 60 * 60 * 24 * 2,
            'metric_window': 1.0,
        }), config)

        worker = yield self.app_helper.get_application(config)
        returnValue(worker)
Beispiel #17
0
 def setUp(self):
     self.app_helper = self.add_helper(ApplicationHelper(CalculatorApp))
     self.worker = yield self.app_helper.get_application({})
Beispiel #18
0
class TestMessageForwardingWorker(JunebugTestBase):
    @inlineCallbacks
    def setUp(self):
        self.logging_api = RequestLoggingApi()
        self.logging_api.setup()
        self.addCleanup(self.logging_api.teardown)
        self.url = self.logging_api.url

        self.worker = yield self.get_worker()
        connection_pool = HTTPConnectionPool(reactor, persistent=False)
        treq._utils.set_global_pool(connection_pool)

    @inlineCallbacks
    def get_worker(self, config=None):
        '''Get a new MessageForwardingWorker with the provided config'''
        if config is None:
            config = {}

        self.app_helper = ApplicationHelper(MessageForwardingWorker)
        yield self.app_helper.setup()
        self.addCleanup(self.app_helper.cleanup)

        persistencehelper = PersistenceHelper()
        yield persistencehelper.setup()
        self.addCleanup(persistencehelper.cleanup)

        config = conjoin(
            persistencehelper.mk_config({
                'transport_name':
                'testtransport',
                'mo_message_url':
                self.url.decode('utf-8'),
                'inbound_ttl':
                60,
                'outbound_ttl':
                60 * 60 * 24 * 2,
                'metric_window':
                1.0,
            }), config)

        worker = yield self.app_helper.get_application(config)
        returnValue(worker)

    @inlineCallbacks
    def assert_event_stored(self, event):
        key = '%s:outbound_messages:%s' % (
            self.worker.config['transport_name'], 'msg-21')
        event_json = yield self.worker.redis.hget(key, event['event_id'])
        self.assertEqual(event_json, event.to_json())

    @inlineCallbacks
    def test_channel_id(self):
        worker = yield self.get_worker({'transport_name': 'foo'})
        self.assertEqual(worker.channel_id, 'foo')

    @inlineCallbacks
    def test_send_message_http(self):
        '''A sent message should be forwarded to the configured URL if a URL
        is set.'''
        msg = TransportUserMessage.send(to_addr='+1234', content='testcontent')
        yield self.worker.consume_user_message(msg)
        [req] = self.logging_api.requests

        self.assert_request(req,
                            method='POST',
                            headers={'content-type': ['application/json']})

        self.assert_body_contains(req, to='+1234', content='testcontent')

    @inlineCallbacks
    def test_send_message_amqp(self):
        '''A sent message should be forwarded to the correct AMQP queue if
        the config option is set.'''
        worker = yield self.get_worker(config={'message_queue': 'testqueue'})
        msg = TransportUserMessage.send(to_addr='+1234', content='testcontent')
        yield worker.consume_user_message(msg)

        [dispatched_msg
         ] = self.app_helper.get_dispatched('testqueue', 'inbound',
                                            TransportUserMessage)

        self.assertEqual(dispatched_msg, msg)

    @inlineCallbacks
    def test_send_message_bad_response(self):
        '''If there is an error sending a message to the configured URL, the
        error and message should be logged'''
        self.patch_logger()
        self.worker = yield self.get_worker({
            'transport_name':
            'testtransport',
            'mo_message_url':
            self.url + '/bad/',
        })
        msg = TransportUserMessage.send(to_addr='+1234', content='testcontent')
        yield self.worker.consume_user_message(msg)

        self.assert_was_logged("'content': 'testcontent'")
        self.assert_was_logged("'to': '+1234'")
        self.assert_was_logged('500')
        self.assert_was_logged('test-error-response')

    @inlineCallbacks
    def test_send_message_storing(self):
        '''Inbound messages should be stored in the InboundMessageStore'''
        msg = TransportUserMessage.send(to_addr='+1234', content='testcontent')
        yield self.worker.consume_user_message(msg)

        redis = self.worker.redis
        key = '%s:inbound_messages:%s' % (self.worker.config['transport_name'],
                                          msg['message_id'])
        msg_json = yield redis.hget(key, 'message')
        self.assertEqual(TransportUserMessage.from_json(msg_json), msg)

    @inlineCallbacks
    def test_receive_message_amqp(self):
        '''A received message on the configured queue should be forwarded to
        the transport queue if the config option is set.'''
        worker = yield self.get_worker(config={'message_queue': 'testqueue'})
        msg = TransportUserMessage.send(to_addr='+1234', content='testcontent')
        yield self.app_helper.dispatch_outbound(msg,
                                                connector_name='testqueue')

        [dispatched_msg] = yield self.app_helper.wait_for_dispatched_outbound(
            connector_name=worker.transport_name)
        self.assertEqual(dispatched_msg, msg)

    @inlineCallbacks
    def test_forward_ack_http(self):
        event = TransportEvent(event_type='ack',
                               user_message_id='msg-21',
                               sent_message_id='msg-21',
                               timestamp='2015-09-22 15:39:44.827794')

        yield self.worker.outbounds.store_event_url(self.worker.channel_id,
                                                    'msg-21', self.url)

        yield self.worker.consume_ack(event)
        [req] = self.logging_api.requests

        self.assert_request(req,
                            method='POST',
                            headers={'content-type': ['application/json']},
                            body=api_from_event(self.worker.channel_id, event))
        yield self.assert_event_stored(event)

    @inlineCallbacks
    def test_forward_ack_amqp(self):
        '''A sent ack event should be forwarded to the correct AMQP queue if
        the config option is set.'''
        worker = yield self.get_worker(config={'message_queue': 'testqueue'})
        event = TransportEvent(event_type='ack',
                               user_message_id='msg-21',
                               sent_message_id='msg-21',
                               timestamp='2015-09-22 15:39:44.827794')

        yield worker.consume_ack(event)

        [dispatched_msg
         ] = self.app_helper.get_dispatched('testqueue', 'event',
                                            TransportEvent)

        self.assertEqual(dispatched_msg['event_id'], event['event_id'])

    @inlineCallbacks
    def test_forward_ack_bad_response(self):
        self.patch_logger()

        event = TransportEvent(event_type='ack',
                               user_message_id='msg-21',
                               sent_message_id='msg-21',
                               timestamp='2015-09-22 15:39:44.827794')

        yield self.worker.outbounds.store_event_url(self.worker.channel_id,
                                                    'msg-21',
                                                    "%s/bad/" % self.url)

        yield self.worker.consume_ack(event)

        self.assert_was_logged(repr(event))
        self.assert_was_logged('500')
        self.assert_was_logged('test-error-response')
        yield self.assert_event_stored(event)

    @inlineCallbacks
    def test_forward_ack_no_message(self):
        self.patch_logger()

        event = TransportEvent(event_type='ack',
                               user_message_id='msg-21',
                               sent_message_id='msg-21',
                               timestamp='2015-09-22 15:39:44.827794')

        yield self.worker.consume_ack(event)

        self.assertEqual(self.logging_api.requests, [])
        yield self.assert_event_stored(event)

    @inlineCallbacks
    def test_forward_nack_http(self):
        event = TransportEvent(event_type='nack',
                               user_message_id='msg-21',
                               nack_reason='too many foos',
                               timestamp='2015-09-22 15:39:44.827794')

        yield self.worker.outbounds.store_event_url(self.worker.channel_id,
                                                    'msg-21', self.url)

        yield self.worker.consume_nack(event)
        [req] = self.logging_api.requests

        self.assert_request(req,
                            method='POST',
                            headers={'content-type': ['application/json']},
                            body=api_from_event(self.worker.channel_id, event))
        yield self.assert_event_stored(event)

    @inlineCallbacks
    def test_forward_nack_amqp(self):
        '''A sent nack event should be forwarded to the correct AMQP queue if
        the config option is set.'''
        worker = yield self.get_worker(config={'message_queue': 'testqueue'})
        event = TransportEvent(event_type='nack',
                               user_message_id='msg-21',
                               nack_reason='too many foos',
                               timestamp='2015-09-22 15:39:44.827794')

        yield worker.consume_nack(event)

        [dispatched_msg
         ] = self.app_helper.get_dispatched('testqueue', 'event',
                                            TransportEvent)

        self.assertEqual(dispatched_msg['event_id'], event['event_id'])

    @inlineCallbacks
    def test_forward_nack_bad_response(self):
        self.patch_logger()

        event = TransportEvent(event_type='nack',
                               user_message_id='msg-21',
                               nack_reason='too many foos',
                               timestamp='2015-09-22 15:39:44.827794')

        yield self.worker.outbounds.store_event_url(self.worker.channel_id,
                                                    'msg-21',
                                                    "%s/bad/" % (self.url, ))

        yield self.worker.consume_nack(event)

        self.assert_was_logged(repr(event))
        self.assert_was_logged('500')
        self.assert_was_logged('test-error-response')
        yield self.assert_event_stored(event)

    @inlineCallbacks
    def test_forward_nack_no_message(self):
        self.patch_logger()

        event = TransportEvent(event_type='nack',
                               user_message_id='msg-21',
                               nack_reason='too many foos',
                               timestamp='2015-09-22 15:39:44.827794')

        yield self.worker.consume_nack(event)

        self.assertEqual(self.logging_api.requests, [])
        yield self.assert_event_stored(event)

    @inlineCallbacks
    def test_forward_dr_http(self):
        event = TransportEvent(event_type='delivery_report',
                               user_message_id='msg-21',
                               delivery_status='pending',
                               timestamp='2015-09-22 15:39:44.827794')

        yield self.worker.outbounds.store_event_url(self.worker.channel_id,
                                                    'msg-21', self.url)

        yield self.worker.consume_delivery_report(event)
        [req] = self.logging_api.requests

        self.assert_request(req,
                            method='POST',
                            headers={'content-type': ['application/json']},
                            body=api_from_event(self.worker.channel_id, event))
        yield self.assert_event_stored(event)

    @inlineCallbacks
    def test_forward_dr_amqp(self):
        '''A sent delivery report event should be forwarded to the correct
        AMQP queue if the config option is set.'''
        worker = yield self.get_worker(config={'message_queue': 'testqueue'})
        event = TransportEvent(event_type='delivery_report',
                               user_message_id='msg-21',
                               delivery_status='pending',
                               timestamp='2015-09-22 15:39:44.827794')

        yield worker.consume_nack(event)

        [dispatched_msg
         ] = self.app_helper.get_dispatched('testqueue', 'event',
                                            TransportEvent)

        self.assertEqual(dispatched_msg['event_id'], event['event_id'])

    @inlineCallbacks
    def test_forward_dr_bad_response(self):
        self.patch_logger()

        event = TransportEvent(event_type='delivery_report',
                               user_message_id='msg-21',
                               delivery_status='pending',
                               timestamp='2015-09-22 15:39:44.827794')

        yield self.worker.outbounds.store_event_url(self.worker.channel_id,
                                                    'msg-21',
                                                    "%s/bad/" % self.url)

        yield self.worker.consume_delivery_report(event)

        self.assert_was_logged(repr(event))
        self.assert_was_logged('500')
        self.assert_was_logged('test-error-response')
        yield self.assert_event_stored(event)

    @inlineCallbacks
    def test_forward_dr_no_message(self):
        self.patch_logger()

        event = TransportEvent(event_type='delivery_report',
                               user_message_id='msg-21',
                               delivery_status='pending',
                               timestamp='2015-09-22 15:39:44.827794')

        yield self.worker.consume_delivery_report(event)

        self.assertEqual(self.logging_api.requests, [])
        yield self.assert_event_stored(event)

    @inlineCallbacks
    def test_forward_event_bad_event(self):
        self.patch_logger()

        event = TransportEvent(event_type='ack',
                               user_message_id='msg-21',
                               sent_message_id='msg-21',
                               timestamp='2015-09-22 15:39:44.827794')

        event['event_type'] = 'bad'

        yield self.worker.outbounds.store_event_url(self.worker.channel_id,
                                                    'msg-21', self.url)

        yield self.worker._forward_event(event)

        self.assertEqual(self.logging_api.requests, [])
        self.assert_was_logged("Discarding unrecognised event %r" % (event, ))

    @inlineCallbacks
    def test_outbound_message_rates(self):
        '''Outbound messages should increase the message send rates.'''
        clock = self.patch_message_rate_clock()

        worker = yield self.get_worker({
            'message_rate_bucket': 1.0,
        })

        msg = TransportUserMessage.send(to_addr='+1234', content='testcontent')
        yield worker.consume_user_message(msg)

        clock.advance(1)

        self.assertEqual((yield worker.message_rate.get_messages_per_second(
            'testtransport', 'inbound', 1.0)), 1.0)

    @inlineCallbacks
    def test_submitted_event_rates(self):
        '''Acknowledge events should increase the submitted event rates.'''
        clock = self.patch_message_rate_clock()

        worker = yield self.get_worker({
            'message_rate_bucket': 1.0,
        })

        event = TransportEvent(event_type='ack',
                               user_message_id='msg-21',
                               sent_message_id='msg-21',
                               timestamp='2015-09-22 15:39:44.827794')
        yield worker.consume_ack(event)

        clock.advance(1)

        self.assertEqual((yield worker.message_rate.get_messages_per_second(
            'testtransport', 'submitted', 1.0)), 1.0)

    @inlineCallbacks
    def test_rejected_event_rates(self):
        '''Not-acknowledge events should increase the rejected event rates.'''
        clock = self.patch_message_rate_clock()

        worker = yield self.get_worker({
            'message_rate_bucket': 1.0,
        })

        event = TransportEvent(event_type='nack',
                               nack_reason='bad message',
                               user_message_id='msg-21',
                               timestamp='2015-09-22 15:39:44.827794')
        yield worker.consume_nack(event)

        clock.advance(1)

        self.assertEqual((yield worker.message_rate.get_messages_per_second(
            'testtransport', 'rejected', 1.0)), 1.0)

    @inlineCallbacks
    def test_delivery_succeeded_event_rates(self):
        '''Delivered delivery reports should increase the delivery_succeeded
        event rates.'''
        clock = self.patch_message_rate_clock()

        worker = yield self.get_worker({
            'message_rate_bucket': 1.0,
        })

        event = TransportEvent(event_type='delivery_report',
                               user_message_id='msg-21',
                               delivery_status='delivered',
                               timestamp='2015-09-22 15:39:44.827794')
        yield worker.consume_delivery_report(event)

        clock.advance(1)

        self.assertEqual((yield worker.message_rate.get_messages_per_second(
            'testtransport', 'delivery_succeeded', 1.0)), 1.0)

    @inlineCallbacks
    def test_delivery_failed_event_rates(self):
        '''Failed delivery reports should increase the delivery_failed
        event rates.'''
        clock = self.patch_message_rate_clock()

        worker = yield self.get_worker({
            'message_rate_bucket': 1.0,
        })

        event = TransportEvent(event_type='delivery_report',
                               user_message_id='msg-21',
                               delivery_status='failed',
                               timestamp='2015-09-22 15:39:44.827794')
        yield worker.consume_delivery_report(event)

        clock.advance(1)

        self.assertEqual((yield worker.message_rate.get_messages_per_second(
            'testtransport', 'delivery_failed', 1.0)), 1.0)

    @inlineCallbacks
    def test_delivery_pending_event_rates(self):
        '''Pending delivery reports should increase the delivery_pending
        event rates.'''
        clock = self.patch_message_rate_clock()

        worker = yield self.get_worker({
            'message_rate_bucket': 1.0,
        })

        event = TransportEvent(event_type='delivery_report',
                               user_message_id='msg-21',
                               delivery_status='pending',
                               timestamp='2015-09-22 15:39:44.827794')
        yield worker.consume_delivery_report(event)

        clock.advance(1)

        self.assertEqual((yield worker.message_rate.get_messages_per_second(
            'testtransport', 'delivery_pending', 1.0)), 1.0)
Beispiel #19
0
 def setUp(self):
     self.app_helper = self.add_helper(
         ApplicationHelper(StaticReplyApplication))
Beispiel #20
0
 def setUp(self):
     yield super(TestHTTPRelay, self).setUp()
     self.path = '/path'
     self.app_helper = self.add_helper(
         ApplicationHelper(HTTPRelayApplication))
Beispiel #21
0
 def test_implements_IHelper(self):
     """
     ApplicationHelper instances should provide the IHelper interface.
     """
     self.assertTrue(IHelper.providedBy(ApplicationHelper(None)))
Beispiel #22
0
class TestMessageForwardingWorker(JunebugTestBase):
    @inlineCallbacks
    def setUp(self):
        self.logging_api = RequestLoggingApi()
        self.logging_api.setup()
        self.addCleanup(self.logging_api.teardown)
        self.url = self.logging_api.url

        self.worker = yield self.get_worker()
        connection_pool = HTTPConnectionPool(reactor, persistent=False)
        treq._utils.set_global_pool(connection_pool)

    @inlineCallbacks
    def get_worker(self, config=None):
        '''Get a new MessageForwardingWorker with the provided config'''
        if config is None:
            config = {}

        self.app_helper = ApplicationHelper(MessageForwardingWorker)
        yield self.app_helper.setup()
        self.addCleanup(self.app_helper.cleanup)

        persistencehelper = PersistenceHelper()
        yield persistencehelper.setup()
        self.addCleanup(persistencehelper.cleanup)

        config = conjoin(persistencehelper.mk_config({
            'transport_name': 'testtransport',
            'mo_message_url': self.url.decode('utf-8'),
            'inbound_ttl': 60,
            'outbound_ttl': 60 * 60 * 24 * 2,
            'metric_window': 1.0,
        }), config)

        worker = yield self.app_helper.get_application(config)
        returnValue(worker)

    @inlineCallbacks
    def assert_event_stored(self, event):
        key = '%s:outbound_messages:%s' % (
            self.worker.config['transport_name'], 'msg-21')
        event_json = yield self.worker.redis.hget(key, event['event_id'])
        self.assertEqual(event_json, event.to_json())

    @inlineCallbacks
    def test_channel_id(self):
        worker = yield self.get_worker({'transport_name': 'foo'})
        self.assertEqual(worker.channel_id, 'foo')

    @inlineCallbacks
    def test_send_message_http(self):
        '''A sent message should be forwarded to the configured URL if a URL
        is set.'''
        msg = TransportUserMessage.send(to_addr='+1234', content='testcontent')
        yield self.worker.consume_user_message(msg)
        [req] = self.logging_api.requests

        self.assert_request(req, method='POST', headers={
            'content-type': ['application/json']
        })

        self.assert_body_contains(req, to='+1234', content='testcontent')

    @inlineCallbacks
    def test_send_message_amqp(self):
        '''A sent message should be forwarded to the correct AMQP queue if
        the config option is set.'''
        worker = yield self.get_worker(config={
            'message_queue': 'testqueue'
        })
        msg = TransportUserMessage.send(to_addr='+1234', content='testcontent')
        yield worker.consume_user_message(msg)

        [dispatched_msg] = self.app_helper.get_dispatched(
            'testqueue', 'inbound', TransportUserMessage)

        self.assertEqual(dispatched_msg, msg)

    @inlineCallbacks
    def test_send_message_bad_response(self):
        '''If there is an error sending a message to the configured URL, the
        error and message should be logged'''
        self.patch_logger()
        self.worker = yield self.get_worker({
            'transport_name': 'testtransport',
            'mo_message_url': self.url + '/bad/',
            })
        msg = TransportUserMessage.send(to_addr='+1234', content='testcontent')
        yield self.worker.consume_user_message(msg)

        self.assert_was_logged("'content': 'testcontent'")
        self.assert_was_logged("'to': '+1234'")
        self.assert_was_logged('500')
        self.assert_was_logged('test-error-response')

    @inlineCallbacks
    def test_send_message_storing(self):
        '''Inbound messages should be stored in the InboundMessageStore'''
        msg = TransportUserMessage.send(to_addr='+1234', content='testcontent')
        yield self.worker.consume_user_message(msg)

        redis = self.worker.redis
        key = '%s:inbound_messages:%s' % (
            self.worker.config['transport_name'], msg['message_id'])
        msg_json = yield redis.hget(key, 'message')
        self.assertEqual(TransportUserMessage.from_json(msg_json), msg)

    @inlineCallbacks
    def test_receive_message_amqp(self):
        '''A received message on the configured queue should be forwarded to
        the transport queue if the config option is set.'''
        worker = yield self.get_worker(config={
            'message_queue': 'testqueue'
        })
        msg = TransportUserMessage.send(to_addr='+1234', content='testcontent')
        yield self.app_helper.dispatch_outbound(
            msg, connector_name='testqueue')

        [dispatched_msg] = yield self.app_helper.wait_for_dispatched_outbound(
            connector_name=worker.transport_name)
        self.assertEqual(dispatched_msg, msg)

    @inlineCallbacks
    def test_forward_ack_http(self):
        event = TransportEvent(
            event_type='ack',
            user_message_id='msg-21',
            sent_message_id='msg-21',
            timestamp='2015-09-22 15:39:44.827794')

        yield self.worker.outbounds.store_event_url(
            self.worker.channel_id, 'msg-21', self.url)

        yield self.worker.consume_ack(event)
        [req] = self.logging_api.requests

        self.assert_request(
            req,
            method='POST',
            headers={'content-type': ['application/json']},
            body=api_from_event(self.worker.channel_id, event))
        yield self.assert_event_stored(event)

    @inlineCallbacks
    def test_forward_ack_amqp(self):
        '''A sent ack event should be forwarded to the correct AMQP queue if
        the config option is set.'''
        worker = yield self.get_worker(config={
            'message_queue': 'testqueue'
        })
        event = TransportEvent(
            event_type='ack',
            user_message_id='msg-21',
            sent_message_id='msg-21',
            timestamp='2015-09-22 15:39:44.827794')

        yield worker.consume_ack(event)

        [dispatched_msg] = self.app_helper.get_dispatched(
            'testqueue', 'event', TransportEvent)

        self.assertEqual(dispatched_msg['event_id'], event['event_id'])

    @inlineCallbacks
    def test_forward_ack_bad_response(self):
        self.patch_logger()

        event = TransportEvent(
            event_type='ack',
            user_message_id='msg-21',
            sent_message_id='msg-21',
            timestamp='2015-09-22 15:39:44.827794')

        yield self.worker.outbounds.store_event_url(
            self.worker.channel_id, 'msg-21', "%s/bad/" % self.url)

        yield self.worker.consume_ack(event)

        self.assert_was_logged(repr(event))
        self.assert_was_logged('500')
        self.assert_was_logged('test-error-response')
        yield self.assert_event_stored(event)

    @inlineCallbacks
    def test_forward_ack_no_message(self):
        self.patch_logger()

        event = TransportEvent(
            event_type='ack',
            user_message_id='msg-21',
            sent_message_id='msg-21',
            timestamp='2015-09-22 15:39:44.827794')

        yield self.worker.consume_ack(event)

        self.assertEqual(self.logging_api.requests, [])
        yield self.assert_event_stored(event)

    @inlineCallbacks
    def test_forward_nack_http(self):
        event = TransportEvent(
            event_type='nack',
            user_message_id='msg-21',
            nack_reason='too many foos',
            timestamp='2015-09-22 15:39:44.827794')

        yield self.worker.outbounds.store_event_url(
            self.worker.channel_id, 'msg-21', self.url)

        yield self.worker.consume_nack(event)
        [req] = self.logging_api.requests

        self.assert_request(
            req,
            method='POST',
            headers={'content-type': ['application/json']},
            body=api_from_event(self.worker.channel_id, event))
        yield self.assert_event_stored(event)

    @inlineCallbacks
    def test_forward_nack_amqp(self):
        '''A sent nack event should be forwarded to the correct AMQP queue if
        the config option is set.'''
        worker = yield self.get_worker(config={
            'message_queue': 'testqueue'
        })
        event = TransportEvent(
            event_type='nack',
            user_message_id='msg-21',
            nack_reason='too many foos',
            timestamp='2015-09-22 15:39:44.827794')

        yield worker.consume_nack(event)

        [dispatched_msg] = self.app_helper.get_dispatched(
            'testqueue', 'event', TransportEvent)

        self.assertEqual(dispatched_msg['event_id'], event['event_id'])

    @inlineCallbacks
    def test_forward_nack_bad_response(self):
        self.patch_logger()

        event = TransportEvent(
            event_type='nack',
            user_message_id='msg-21',
            nack_reason='too many foos',
            timestamp='2015-09-22 15:39:44.827794')

        yield self.worker.outbounds.store_event_url(
            self.worker.channel_id, 'msg-21', "%s/bad/" % (self.url,))

        yield self.worker.consume_nack(event)

        self.assert_was_logged(repr(event))
        self.assert_was_logged('500')
        self.assert_was_logged('test-error-response')
        yield self.assert_event_stored(event)

    @inlineCallbacks
    def test_forward_nack_no_message(self):
        self.patch_logger()

        event = TransportEvent(
            event_type='nack',
            user_message_id='msg-21',
            nack_reason='too many foos',
            timestamp='2015-09-22 15:39:44.827794')

        yield self.worker.consume_nack(event)

        self.assertEqual(self.logging_api.requests, [])
        yield self.assert_event_stored(event)

    @inlineCallbacks
    def test_forward_dr_http(self):
        event = TransportEvent(
            event_type='delivery_report',
            user_message_id='msg-21',
            delivery_status='pending',
            timestamp='2015-09-22 15:39:44.827794')

        yield self.worker.outbounds.store_event_url(
            self.worker.channel_id, 'msg-21', self.url)

        yield self.worker.consume_delivery_report(event)
        [req] = self.logging_api.requests

        self.assert_request(
            req,
            method='POST',
            headers={'content-type': ['application/json']},
            body=api_from_event(self.worker.channel_id, event))
        yield self.assert_event_stored(event)

    @inlineCallbacks
    def test_forward_dr_amqp(self):
        '''A sent delivery report event should be forwarded to the correct
        AMQP queue if the config option is set.'''
        worker = yield self.get_worker(config={
            'message_queue': 'testqueue'
        })
        event = TransportEvent(
            event_type='delivery_report',
            user_message_id='msg-21',
            delivery_status='pending',
            timestamp='2015-09-22 15:39:44.827794')

        yield worker.consume_nack(event)

        [dispatched_msg] = self.app_helper.get_dispatched(
            'testqueue', 'event', TransportEvent)

        self.assertEqual(dispatched_msg['event_id'], event['event_id'])

    @inlineCallbacks
    def test_forward_dr_bad_response(self):
        self.patch_logger()

        event = TransportEvent(
            event_type='delivery_report',
            user_message_id='msg-21',
            delivery_status='pending',
            timestamp='2015-09-22 15:39:44.827794')

        yield self.worker.outbounds.store_event_url(
            self.worker.channel_id, 'msg-21', "%s/bad/" % self.url)

        yield self.worker.consume_delivery_report(event)

        self.assert_was_logged(repr(event))
        self.assert_was_logged('500')
        self.assert_was_logged('test-error-response')
        yield self.assert_event_stored(event)

    @inlineCallbacks
    def test_forward_dr_no_message(self):
        self.patch_logger()

        event = TransportEvent(
            event_type='delivery_report',
            user_message_id='msg-21',
            delivery_status='pending',
            timestamp='2015-09-22 15:39:44.827794')

        yield self.worker.consume_delivery_report(event)

        self.assertEqual(self.logging_api.requests, [])
        yield self.assert_event_stored(event)

    @inlineCallbacks
    def test_forward_event_bad_event(self):
        self.patch_logger()

        event = TransportEvent(
            event_type='ack',
            user_message_id='msg-21',
            sent_message_id='msg-21',
            timestamp='2015-09-22 15:39:44.827794')

        event['event_type'] = 'bad'

        yield self.worker.outbounds.store_event_url(
            self.worker.channel_id, 'msg-21', self.url)

        yield self.worker._forward_event(event)

        self.assertEqual(self.logging_api.requests, [])
        self.assert_was_logged("Discarding unrecognised event %r" % (event,))

    @inlineCallbacks
    def test_outbound_message_rates(self):
        '''Outbound messages should increase the message send rates.'''
        clock = self.patch_message_rate_clock()

        worker = yield self.get_worker({
            'message_rate_bucket': 1.0,
        })

        msg = TransportUserMessage.send(to_addr='+1234', content='testcontent')
        yield worker.consume_user_message(msg)

        clock.advance(1)

        self.assertEqual((yield worker.message_rate.get_messages_per_second(
            'testtransport', 'inbound', 1.0)), 1.0)

    @inlineCallbacks
    def test_submitted_event_rates(self):
        '''Acknowledge events should increase the submitted event rates.'''
        clock = self.patch_message_rate_clock()

        worker = yield self.get_worker({
            'message_rate_bucket': 1.0,
        })

        event = TransportEvent(
            event_type='ack',
            user_message_id='msg-21',
            sent_message_id='msg-21',
            timestamp='2015-09-22 15:39:44.827794')
        yield worker.consume_ack(event)

        clock.advance(1)

        self.assertEqual((yield worker.message_rate.get_messages_per_second(
            'testtransport', 'submitted', 1.0)), 1.0)

    @inlineCallbacks
    def test_rejected_event_rates(self):
        '''Not-acknowledge events should increase the rejected event rates.'''
        clock = self.patch_message_rate_clock()

        worker = yield self.get_worker({
            'message_rate_bucket': 1.0,
        })

        event = TransportEvent(
            event_type='nack',
            nack_reason='bad message',
            user_message_id='msg-21',
            timestamp='2015-09-22 15:39:44.827794')
        yield worker.consume_nack(event)

        clock.advance(1)

        self.assertEqual((yield worker.message_rate.get_messages_per_second(
            'testtransport', 'rejected', 1.0)), 1.0)

    @inlineCallbacks
    def test_delivery_succeeded_event_rates(self):
        '''Delivered delivery reports should increase the delivery_succeeded
        event rates.'''
        clock = self.patch_message_rate_clock()

        worker = yield self.get_worker({
            'message_rate_bucket': 1.0,
        })

        event = TransportEvent(
            event_type='delivery_report',
            user_message_id='msg-21',
            delivery_status='delivered',
            timestamp='2015-09-22 15:39:44.827794')
        yield worker.consume_delivery_report(event)

        clock.advance(1)

        self.assertEqual((yield worker.message_rate.get_messages_per_second(
            'testtransport', 'delivery_succeeded', 1.0)), 1.0)

    @inlineCallbacks
    def test_delivery_failed_event_rates(self):
        '''Failed delivery reports should increase the delivery_failed
        event rates.'''
        clock = self.patch_message_rate_clock()

        worker = yield self.get_worker({
            'message_rate_bucket': 1.0,
        })

        event = TransportEvent(
            event_type='delivery_report',
            user_message_id='msg-21',
            delivery_status='failed',
            timestamp='2015-09-22 15:39:44.827794')
        yield worker.consume_delivery_report(event)

        clock.advance(1)

        self.assertEqual((yield worker.message_rate.get_messages_per_second(
            'testtransport', 'delivery_failed', 1.0)), 1.0)

    @inlineCallbacks
    def test_delivery_pending_event_rates(self):
        '''Pending delivery reports should increase the delivery_pending
        event rates.'''
        clock = self.patch_message_rate_clock()

        worker = yield self.get_worker({
            'message_rate_bucket': 1.0,
        })

        event = TransportEvent(
            event_type='delivery_report',
            user_message_id='msg-21',
            delivery_status='pending',
            timestamp='2015-09-22 15:39:44.827794')
        yield worker.consume_delivery_report(event)

        clock.advance(1)

        self.assertEqual((yield worker.message_rate.get_messages_per_second(
            'testtransport', 'delivery_pending', 1.0)), 1.0)
Beispiel #23
0
 def setUp(self):
     self.app_helper = self.add_helper(
         ApplicationHelper(DummyApplicationWorker))
     self.worker = yield self.app_helper.get_application({})
Beispiel #24
0
 def setUp(self):
     self.app_helper = self.add_helper(
         ApplicationHelper(RockPaperScissorsWorker))
     self.worker = yield self.app_helper.get_application({})
Beispiel #25
0
 def setUp(self):
     self.app_helper = self.add_helper(ApplicationHelper(ApplicationWorker))
Beispiel #26
0
 def setUp(self):
     self.app_helper = self.add_helper(ApplicationHelper(None))
     self.worker = yield self.app_helper.get_application({}, EchoTestApp)
Beispiel #27
0
 def setUp(self):
     self.app_helper = self.add_helper(ApplicationHelper(None))
     self.worker = yield self.app_helper.get_application({},
                                                         WordCountWorker)
Beispiel #28
0
 def setUp(self):
     self.app_helper = self.add_helper(ApplicationHelper(RapidSMSRelay))
Beispiel #29
0
 def setUp(self):
     self.app_helper = self.add_helper(ApplicationHelper(MemoWorker))
     self.worker = yield self.app_helper.get_application(
         {'worker_name': 'testmemo'})
     yield self.worker.redis._purge_all()  # just in case
Beispiel #30
0
 def setUp(self):
     self.app_helper = self.add_helper(
         ApplicationHelper(WikipediaWorker, transport_type='ussd'))
     self.fake_api = self.start_webserver(WIKIPEDIA_RESPONSES)
     self.fake_uss = self.start_webserver(USS_RESPONSES)
Beispiel #31
0
 def setUp(self):
     self.app_helper = self.add_helper(ApplicationHelper(TicTacToeWorker))
     self.worker = yield self.app_helper.get_application({})