Example #1
0
    def test_hit_ratelimits(self) -> None:
        user = self.example_user('cordelia')
        email = user.email
        clear_history(RateLimitedUser(user))

        start_time = time.time()
        for i in range(6):
            with mock.patch('time.time', return_value=(start_time + i * 0.1)):
                result = self.send_api_message(email, "some stuff %s" % (i, ))

        self.assertEqual(result.status_code, 429)
        json = result.json()
        self.assertEqual(json.get("result"), "error")
        self.assertIn("API usage exceeded rate limit", json.get("msg"))
        self.assertEqual(json.get('retry-after'), 0.5)
        self.assertTrue('Retry-After' in result)
        self.assertEqual(result['Retry-After'], '0.5')

        # We actually wait a second here, rather than force-clearing our history,
        # to make sure the rate-limiting code automatically forgives a user
        # after some time has passed.
        with mock.patch('time.time', return_value=(start_time + 1.0)):
            result = self.send_api_message(email, "Good message")

            self.assert_json_success(result)
Example #2
0
    def test_hit_ratelimits(self) -> None:
        user = self.example_user('cordelia')
        email = user.email
        clear_history(RateLimitedUser(user))

        start_time = time.time()
        for i in range(6):
            with mock.patch('time.time', return_value=(start_time + i * 0.1)):
                result = self.send_api_message(email, "some stuff %s" % (i,))

        self.assertEqual(result.status_code, 429)
        json = result.json()
        self.assertEqual(json.get("result"), "error")
        self.assertIn("API usage exceeded rate limit", json.get("msg"))
        self.assertEqual(json.get('retry-after'), 0.5)
        self.assertTrue('Retry-After' in result)
        self.assertEqual(result['Retry-After'], '0.5')

        # We actually wait a second here, rather than force-clearing our history,
        # to make sure the rate-limiting code automatically forgives a user
        # after some time has passed.
        with mock.patch('time.time', return_value=(start_time + 1.0)):
            result = self.send_api_message(email, "Good message")

            self.assert_json_success(result)
Example #3
0
    def test_headers(self) -> None:
        user = self.example_user('hamlet')
        clear_history(RateLimitedUser(user))

        result = self.send_api_message(user, "some stuff")
        self.assertTrue('X-RateLimit-Remaining' in result)
        self.assertTrue('X-RateLimit-Limit' in result)
        self.assertTrue('X-RateLimit-Reset' in result)
    def test_mirror_worker_rate_limiting(self, mock_mirror_email: MagicMock,
                                         mock_warn: MagicMock) -> None:
        fake_client = self.FakeClient()
        realm = get_realm('zulip')
        clear_history(RateLimitedRealmMirror(realm))
        stream = get_stream('Denmark', realm)
        stream_to_address = encode_email_address(stream)
        data = [
            dict(
                message=u'\xf3test',
                time=time.time(),
                rcpt_to=stream_to_address
            )
        ] * 5
        for element in data:
            fake_client.queue.append(('email_mirror', element))

        with simulated_queue_client(lambda: fake_client):
            start_time = time.time()
            with patch('time.time', return_value=start_time):
                worker = queue_processors.MirrorWorker()
                worker.setup()
                worker.start()
                # Of the first 5 messages, only 2 should be processed
                # (the rest being rate-limited):
                self.assertEqual(mock_mirror_email.call_count, 2)

                # If a new message is sent into the stream mirror, it will get rejected:
                fake_client.queue.append(('email_mirror', data[0]))
                worker.start()
                self.assertEqual(mock_mirror_email.call_count, 2)

                # However, missed message emails don't get rate limited:
                with self.settings(EMAIL_GATEWAY_PATTERN="*****@*****.**"):
                    address = 'mm' + ('x' * 32) + '@example.com'
                    event = dict(
                        message=u'\xf3test',
                        time=time.time(),
                        rcpt_to=address
                    )
                    fake_client.queue.append(('email_mirror', event))
                    worker.start()
                    self.assertEqual(mock_mirror_email.call_count, 3)

            # After some times passes, emails get accepted again:
            with patch('time.time', return_value=(start_time + 11.0)):
                fake_client.queue.append(('email_mirror', data[0]))
                worker.start()
                self.assertEqual(mock_mirror_email.call_count, 4)

                # If RateLimiterLockingException is thrown, we rate-limit the new message:
                with patch('zerver.lib.rate_limiter.incr_ratelimit',
                           side_effect=RateLimiterLockingException):
                    fake_client.queue.append(('email_mirror', data[0]))
                    worker.start()
                    self.assertEqual(mock_mirror_email.call_count, 4)
                    expected_warn = "Deadlock trying to incr_ratelimit for RateLimitedRealmMirror:zulip"
                    mock_warn.assert_called_with(expected_warn)
Example #5
0
    def test_ratelimit_decrease(self) -> None:
        user = self.example_user('hamlet')
        clear_history(RateLimitedUser(user))
        result = self.send_api_message(user, "some stuff")
        limit = int(result['X-RateLimit-Remaining'])

        result = self.send_api_message(user, "some stuff 2")
        newlimit = int(result['X-RateLimit-Remaining'])
        self.assertEqual(limit, newlimit + 1)
Example #6
0
    def test_headers(self) -> None:
        user = self.example_user('hamlet')
        email = user.email
        clear_history(RateLimitedUser(user))

        result = self.send_api_message(email, "some stuff")
        self.assertTrue('X-RateLimit-Remaining' in result)
        self.assertTrue('X-RateLimit-Limit' in result)
        self.assertTrue('X-RateLimit-Reset' in result)
Example #7
0
    def test_hit_ratelimiterlockingexception(self) -> None:
        user = self.example_user('cordelia')
        email = user.email
        clear_history(RateLimitedUser(user))

        with mock.patch('zerver.decorator.incr_ratelimit',
                        side_effect=RateLimiterLockingException):
            result = self.send_api_message(email, "some stuff")
            self.assertEqual(result.status_code, 429)
Example #8
0
    def test_ratelimit_decrease(self) -> None:
        user = self.example_user('hamlet')
        email = user.email
        clear_history(RateLimitedUser(user))
        result = self.send_api_message(email, "some stuff")
        limit = int(result['X-RateLimit-Remaining'])

        result = self.send_api_message(email, "some stuff 2")
        newlimit = int(result['X-RateLimit-Remaining'])
        self.assertEqual(limit, newlimit + 1)
Example #9
0
    def test_hit_ratelimiterlockingexception(self, mock_warn: mock.MagicMock) -> None:
        user = self.example_user('cordelia')
        email = user.email
        clear_history(RateLimitedUser(user))

        with mock.patch('zerver.lib.rate_limiter.incr_ratelimit',
                        side_effect=RateLimiterLockingException):
            result = self.send_api_message(email, "some stuff")
            self.assertEqual(result.status_code, 429)
            mock_warn.assert_called_with("Deadlock trying to incr_ratelimit for RateLimitedUser:Id: %s"
                                         % (user.id,))