class DjangoClientTest(TestCase): # Fixture setup/teardown urls = 'tests.contrib.django.urls' def setUp(self): self.raven = get_client() self.handler = SentryDjangoHandler(self.raven) self.handler.install() self.addCleanup(self.handler.uninstall) def test_basic(self): self.raven.captureMessage(message='foo') assert len(self.raven.events) == 1 event = self.raven.events.pop(0) assert 'sentry.interfaces.Message' in event message = event['sentry.interfaces.Message'] assert message['message'] == 'foo' assert event['level'] == logging.ERROR assert event['message'] == 'foo' assert isinstance(event['timestamp'], datetime.datetime) def test_signal_integration(self): try: int(None) except Exception: got_request_exception.send(sender=self.__class__, request=None) else: self.fail('Expected an exception.') assert len(self.raven.events) == 1 event = self.raven.events.pop(0) assert 'exception' in event exc = event['exception']['values'][-1] assert exc['type'] == 'TypeError' assert exc['value'], "int() argument must be a string or a number == not 'NoneType'" assert event['level'] == logging.ERROR assert event['message'], "TypeError: int() argument must be a string or a number == not 'NoneType'" @pytest.mark.skipif(sys.version_info[:2] == (2, 6), reason='Python 2.6') def test_view_exception(self): path = reverse('sentry-raise-exc') self.assertRaises(Exception, self.client.get, path) assert len(self.raven.events) == 1 event = self.raven.events.pop(0) assert 'exception' in event exc = event['exception']['values'][-1] assert exc['type'] == 'Exception' assert exc['value'] == 'view exception' assert event['level'] == logging.ERROR assert event['message'] == 'Exception: view exception' assert 'request' in event assert event['request']['url'] == 'http://testserver{}'.format(path) def test_request_data_unavailable_if_request_is_read(self): with Settings(**{MIDDLEWARE_ATTR: []}): path = reverse('sentry-readrequest-raise-exc') self.assertRaises( AppError, self.client.post, path, '{"a":"b"}', content_type='application/json') assert len(self.raven.events) == 1 event = self.raven.events.pop(0) assert event['request']['data'] == '<unavailable>' def test_djangorestframeworkcompatmiddleware_fills_request_data(self): with Settings(**{MIDDLEWARE_ATTR: [ 'raven.contrib.django.middleware.DjangoRestFrameworkCompatMiddleware']}): path = reverse('sentry-readrequest-raise-exc') self.assertRaises( AppError, self.client.post, path, '{"a":"b"}', content_type='application/json') assert len(self.raven.events) == 1 event = self.raven.events.pop(0) assert event['request']['data'] == '{"a":"b"}' def test_capture_event_with_request_middleware(self): path = reverse('sentry-trigger-event') resp = self.client.get(path) assert resp.status_code == 200 assert len(self.raven.events) == 1 event = self.raven.events.pop(0) assert event['message'] == 'test' assert 'request' in event assert event['request']['url'] == 'http://testserver{}'.format(path) def test_user_info(self): with Settings(**{MIDDLEWARE_ATTR: [ 'django.contrib.sessions.middleware.SessionMiddleware', 'django.contrib.auth.middleware.AuthenticationMiddleware']}): self.assertRaises(Exception, self.client.get, reverse('sentry-raise-exc')) assert len(self.raven.events) == 1 event = self.raven.events.pop(0) assert 'user' in event user_info = event['user'] assert user_info == {'ip_address': '127.0.0.1'} assert self.client.login(username='******', password='******') self.assertRaises(Exception, self.client.get, reverse('sentry-raise-exc')) assert len(self.raven.events) == 1 event = self.raven.events.pop(0) assert 'user' in event user_info = event['user'] assert user_info == { 'ip_address': '127.0.0.1', 'username': self.user.username, 'id': self.user.id, 'email': self.user.email, } @pytest.mark.skipif(not DJANGO_15, reason='< Django 1.5') def test_get_user_info_abstract_user(self): from django.db import models from django.http import HttpRequest from django.contrib.auth.models import AbstractBaseUser class MyUser(AbstractBaseUser): USERNAME_FIELD = 'username' username = models.CharField(max_length=32) email = models.EmailField() user = MyUser( username='******', email='*****@*****.**', id=1, ) request = HttpRequest() request.META['REMOTE_ADDR'] = '127.0.0.1' request.user = user user_info = self.raven.get_user_info(request) assert user_info == { 'ip_address': '127.0.0.1', 'username': user.username, 'id': user.id, 'email': user.email, } request = HttpRequest() request.META['REMOTE_ADDR'] = '127.0.0.1' request.META['HTTP_X_FORWARDED_FOR'] = '1.1.1.1, 2.2.2.2' request.user = user user_info = self.raven.get_user_info(request) assert user_info == { 'ip_address': '1.1.1.1', 'username': user.username, 'id': user.id, 'email': user.email, } @pytest.mark.skipif(not DJANGO_110, reason='< Django 1.10') def test_get_user_info_is_authenticated_property(self): from django.db import models from django.http import HttpRequest from django.contrib.auth.models import AbstractBaseUser class MyUser(AbstractBaseUser): USERNAME_FIELD = 'username' username = models.CharField(max_length=32) email = models.EmailField() @property def is_authenticated(self): return True user = MyUser( username='******', email='*****@*****.**', id=1, ) request = HttpRequest() request.META['REMOTE_ADDR'] = '127.0.0.1' request.user = user user_info = self.raven.get_user_info(request) assert user_info == { 'ip_address': '127.0.0.1', 'username': user.username, 'id': user.id, 'email': user.email, } request = HttpRequest() request.META['REMOTE_ADDR'] = '127.0.0.1' request.META['HTTP_X_FORWARDED_FOR'] = '1.1.1.1, 2.2.2.2' request.user = user user_info = self.raven.get_user_info(request) assert user_info == { 'ip_address': '1.1.1.1', 'username': user.username, 'id': user.id, 'email': user.email, } def test_request_middleware_exception(self): with Settings(**{MIDDLEWARE_ATTR: ['tests.contrib.django.middleware.BrokenRequestMiddleware']}): self.assertRaises(ImportError, self.client.get, reverse('sentry-raise-exc')) assert len(self.raven.events) == 1 event = self.raven.events.pop(0) assert 'exception' in event exc = event['exception']['values'][-1] assert exc['type'] == 'ImportError' assert exc['value'] == 'request' assert event['level'] == logging.ERROR assert event['message'] == 'ImportError: request' def test_response_middlware_exception(self): if django.VERSION[:2] < (1, 3): return with Settings(**{MIDDLEWARE_ATTR: ['tests.contrib.django.middleware.BrokenResponseMiddleware']}): self.assertRaises(ImportError, self.client.get, reverse('sentry-no-error')) assert len(self.raven.events) == 1 event = self.raven.events.pop(0) assert 'exception' in event exc = event['exception']['values'][-1] assert exc['type'] == 'ImportError' assert exc['value'] == 'response' assert event['level'] == logging.ERROR assert event['message'] == 'ImportError: response' def test_broken_500_handler_with_middleware(self): with Settings(BREAK_THAT_500=True, INSTALLED_APPS=['raven.contrib.django']): client = DjangoTestClient(REMOTE_ADDR='127.0.0.1') client.handler = MockSentryMiddleware(MockClientHandler()) self.assertRaises(Exception, client.get, reverse('sentry-raise-exc')) assert len(self.raven.events) == 2 or 4 # TODO: ash remove duplicate client events event = self.raven.events.pop(0) assert 'exception' in event exc = event['exception']['values'][-1] assert exc['type'] == 'Exception' assert exc['value'] == 'view exception' assert event['level'] == logging.ERROR assert event['message'] == 'Exception: view exception' event = self.raven.events.pop(0) assert 'exception' in event exc = event['exception']['values'][-1] assert exc['type'] == 'ValueError' assert exc['value'] == 'handler500' assert event['level'] == logging.ERROR assert event['message'] == 'ValueError: handler500' def test_view_middleware_exception(self): with Settings(**{MIDDLEWARE_ATTR: ['tests.contrib.django.middleware.BrokenViewMiddleware']}): self.assertRaises(ImportError, self.client.get, reverse('sentry-raise-exc')) assert len(self.raven.events) == 1 event = self.raven.events.pop(0) assert 'exception' in event exc = event['exception']['values'][-1] assert exc['type'] == 'ImportError' assert exc['value'] == 'view' assert event['level'] == logging.ERROR assert event['message'] == 'ImportError: view' @pytest.mark.skipif(DJANGO_18, reason='Django 1.8+ not supported') def test_template_name_as_view(self): self.assertRaises(TemplateSyntaxError, self.client.get, reverse('sentry-template-exc')) assert len(self.raven.events) == 1 event = self.raven.events.pop(0) assert event['culprit'] == 'error.html' # def test_request_in_logging(self): # resp = self.client.get(reverse('sentry-log-request-exc')) # assert resp.status_code == 200 # assert len(self.raven.events) == 1 # event = self.raven.events.pop(0) # assert event['culprit'] == 'tests.contrib.django.views in logging_request_exc' # assert event['data']['META']['REMOTE_ADDR'] == '127.0.0.1' # TODO: Python bug #10805 @pytest.mark.skipif(not PY2, reason='Python 2') def test_record_none_exc_info(self): # sys.exc_info can return (None, None, None) if no exception is being # handled anywhere on the stack. See: # http://docs.python.org/library/sys.html#sys.exc_info record = logging.LogRecord( 'foo', logging.INFO, pathname=None, lineno=None, msg='test', args=(), exc_info=(None, None, None), ) handler = SentryHandler() handler.emit(record) assert len(self.raven.events) == 1 event = self.raven.events.pop(0) assert event['message'] == 'test' def test_404_middleware(self): with Settings(**{MIDDLEWARE_ATTR: ['raven.contrib.django.middleware.Sentry404CatchMiddleware']}): resp = self.client.get('/non-existent-page') assert resp.status_code == 404 assert len(self.raven.events) == 1, [e['message'] for e in self.raven.events] event = self.raven.events.pop(0) assert event['level'] == logging.INFO assert event['logger'] == 'http404' assert 'request' in event http = event['request'] assert http['url'] == 'http://testserver/non-existent-page' assert http['method'] == 'GET' assert http['query_string'] == '' assert http['data'] is None def test_404_middleware_when_disabled(self): extra_settings = { MIDDLEWARE_ATTR: ['raven.contrib.django.middleware.Sentry404CatchMiddleware'], 'SENTRY_CLIENT': 'tests.contrib.django.tests.DisabledMockClient', } with Settings(**extra_settings): resp = self.client.get('/non-existent-page') assert resp.status_code == 404 assert self.raven.events == [] def test_invalid_client(self): extra_settings = { 'SENTRY_CLIENT': 'raven.contrib.django.DjangoClient', # default } # Should return fallback client (MockClient) client = get_client('nonexistent.and.invalid') # client should be valid, and the same as with the next call. assert client is get_client() with Settings(**extra_settings): assert isinstance(get_client(), DjangoClient) def test_transport_specification(self): extra_settings = { 'SENTRY_TRANSPORT': 'raven.transport.HTTPTransport', 'SENTRY_DSN': 'http://*****:*****@example.com/1', } with Settings(**extra_settings): client = get_client(reset=True) assert type(client.remote.get_transport()) is HTTPTransport def test_response_error_id_middleware(self): # TODO: test with 500s with Settings(**{MIDDLEWARE_ATTR: [ 'raven.contrib.django.middleware.SentryResponseErrorIdMiddleware', 'raven.contrib.django.middleware.Sentry404CatchMiddleware']}): resp = self.client.get('/non-existent-page') assert resp.status_code == 404 headers = dict(resp.items()) assert 'X-Sentry-ID' in headers assert len(self.raven.events) == 1 event = self.raven.events.pop(0) assert event['event_id'] == headers['X-Sentry-ID'] def test_get_client(self): assert get_client() == get_client() assert get_client('raven.base.Client').__class__ == Client assert get_client() == self.raven assert get_client('%s.%s' % (type(self.raven).__module__, type(self.raven).__name__)) == self.raven assert get_client() == self.raven def test_raw_post_data_partial_read(self): v = '{"foo": "bar"}' request = make_request() request.environ.update({ 'wsgi.input': StringIO(v + '\r\n\r\n'), 'CONTENT_TYPE': 'application/octet-stream', 'CONTENT_LENGTH': len(v), }) request.read(1) self.raven.captureMessage(message='foo', request=request) assert len(self.raven.events) == 1 event = self.raven.events.pop(0) assert 'request' in event http = event['request'] assert http['method'] == 'POST' assert http['data'] == '<unavailable>' def test_read_post_data(self): request = make_request() request.POST = QueryDict("foo=bar&ham=spam") request.read(1) self.raven.captureMessage(message='foo', request=request) assert len(self.raven.events) == 1 event = self.raven.events.pop(0) assert 'request' in event http = event['request'] assert http['method'] == 'POST' assert http['data'] == {'foo': 'bar', 'ham': 'spam'} def test_request_capture(self): request = make_request() request.read(1) self.raven.captureMessage(message='foo', request=request) assert len(self.raven.events) == 1 event = self.raven.events.pop(0) assert 'request' in event http = event['request'] assert http['method'] == 'POST' assert http['data'] == '<unavailable>' assert 'headers' in http headers = http['headers'] assert 'Content-Type' in headers, headers.keys() assert headers['Content-Type'] == 'text/html' env = http['env'] assert 'SERVER_NAME' in env, env.keys() assert env['SERVER_NAME'] == 'testserver' assert 'SERVER_PORT' in env, env.keys() assert env['SERVER_PORT'] == '80' def test_marks_django_frames_correctly(self): self.assertRaises(TemplateSyntaxError, self.client.get, reverse('sentry-template-exc')) assert len(self.raven.events) == 1 event = self.raven.events.pop(0) frames = event['exception']['values'][-1]['stacktrace']['frames'] for frame in frames: if frame['module'].startswith('django.'): assert frame.get('in_app') is False def test_adds_site_to_tags(self): self.assertRaises(TemplateSyntaxError, self.client.get, reverse('sentry-template-exc')) assert len(self.raven.events) == 1 event = self.raven.events.pop(0) tags = event['tags'] assert 'site' in event['tags'] assert tags['site'] == 'example.com' def test_adds_site_to_tags_fallback(self): with Settings(SITE_ID=12345): # nonexistent site, should fallback to SITE_ID self.assertRaises(TemplateSyntaxError, self.client.get, reverse('sentry-template-exc')) assert len(self.raven.events) == 1 event = self.raven.events.pop(0) tags = event['tags'] assert 'site' in event['tags'] assert tags['site'] == 12345 def test_settings_site_overrides_contrib(self): self.raven.site = 'FOO' self.assertRaises(TemplateSyntaxError, self.client.get, reverse('sentry-template-exc')) assert len(self.raven.events) == 1 event = self.raven.events.pop(0) tags = event['tags'] assert 'site' in event['tags'] assert tags['site'] == 'FOO' @mock.patch.object(WSGIRequest, 'build_absolute_uri') def test_suspicious_operation_in_build_absolute_uri(self, build_absolute_uri): build_absolute_uri.side_effect = SuspiciousOperation() request = make_request() request.META['HTTP_HOST'] = 'example.com' result = self.raven.get_data_from_request(request) build_absolute_uri.assert_called_once_with() assert 'request' in result assert result['request']['url'] == 'http://example.com/'
class DjangoClientTest(TestCase): # Fixture setup/teardown urls = 'tests.contrib.django.urls' def setUp(self): self.raven = get_client() self.handler = SentryDjangoHandler(self.raven) self.handler.install() self.addCleanup(self.handler.uninstall) def test_basic(self): self.raven.captureMessage(message='foo') assert len(self.raven.events) == 1 event = self.raven.events.pop(0) assert 'sentry.interfaces.Message' in event message = event['sentry.interfaces.Message'] assert message['message'] == 'foo' assert event['level'] == logging.ERROR assert event['message'] == 'foo' assert isinstance(event['timestamp'], datetime.datetime) def test_signal_integration(self): try: int(None) except Exception: got_request_exception.send(sender=self.__class__, request=None) else: self.fail('Expected an exception.') assert len(self.raven.events) == 1 event = self.raven.events.pop(0) assert 'exception' in event exc = event['exception']['values'][-1] assert exc['type'] == 'TypeError' assert exc['value'], "int() argument must be a string or a number == not 'NoneType'" assert event['level'] == logging.ERROR assert event['message'], "TypeError: int() argument must be a string or a number == not 'NoneType'" @pytest.mark.skipif(sys.version_info[:2] == (2, 6), reason='Python 2.6') def test_view_exception(self): self.assertRaises(Exception, self.client.get, reverse('sentry-raise-exc')) assert len(self.raven.events) == 1 event = self.raven.events.pop(0) assert 'exception' in event exc = event['exception']['values'][-1] assert exc['type'] == 'Exception' assert exc['value'] == 'view exception' assert event['level'] == logging.ERROR assert event['message'] == 'Exception: view exception' def test_user_info(self): with Settings(MIDDLEWARE_CLASSES=[ 'django.contrib.sessions.middleware.SessionMiddleware', 'django.contrib.auth.middleware.AuthenticationMiddleware']): user = User(username='******', email='*****@*****.**') user.set_password('admin') user.save() self.assertRaises(Exception, self.client.get, reverse('sentry-raise-exc')) assert len(self.raven.events) == 1 event = self.raven.events.pop(0) assert 'user' not in event assert self.client.login(username='******', password='******') self.assertRaises(Exception, self.client.get, reverse('sentry-raise-exc')) assert len(self.raven.events) == 1 event = self.raven.events.pop(0) assert 'user' in event user_info = event['user'] assert user_info == { 'username': user.username, 'id': user.id, 'email': user.email, } @pytest.mark.skipif(not DJANGO_15, reason='< Django 1.5') def test_get_user_info_abstract_user(self): from django.db import models from django.contrib.auth.models import AbstractBaseUser class MyUser(AbstractBaseUser): USERNAME_FIELD = 'username' username = models.CharField(max_length=32) email = models.EmailField() user = MyUser( username='******', email='*****@*****.**', id=1, ) user_info = self.raven.get_user_info(user) assert user_info == { 'username': user.username, 'id': user.id, 'email': user.email, } @pytest.mark.skipif(not DJANGO_110, reason='< Django 1.10') def test_get_user_info_is_authenticated_property(self): from django.db import models from django.contrib.auth.models import AbstractBaseUser class MyUser(AbstractBaseUser): USERNAME_FIELD = 'username' username = models.CharField(max_length=32) email = models.EmailField() @property def is_authenticated(self): return True user = MyUser( username='******', email='*****@*****.**', id=1, ) user_info = self.raven.get_user_info(user) assert user_info == { 'username': user.username, 'id': user.id, 'email': user.email, } def test_request_middleware_exception(self): with Settings(MIDDLEWARE_CLASSES=['tests.contrib.django.middleware.BrokenRequestMiddleware']): self.assertRaises(ImportError, self.client.get, reverse('sentry-raise-exc')) assert len(self.raven.events) == 1 event = self.raven.events.pop(0) assert 'exception' in event exc = event['exception']['values'][-1] assert exc['type'] == 'ImportError' assert exc['value'] == 'request' assert event['level'] == logging.ERROR assert event['message'] == 'ImportError: request' def test_response_middlware_exception(self): if django.VERSION[:2] < (1, 3): return with Settings(MIDDLEWARE_CLASSES=['tests.contrib.django.middleware.BrokenResponseMiddleware']): self.assertRaises(ImportError, self.client.get, reverse('sentry-no-error')) assert len(self.raven.events) == 1 event = self.raven.events.pop(0) assert 'exception' in event exc = event['exception']['values'][-1] assert exc['type'] == 'ImportError' assert exc['value'] == 'response' assert event['level'] == logging.ERROR assert event['message'] == 'ImportError: response' def test_broken_500_handler_with_middleware(self): with Settings(BREAK_THAT_500=True, INSTALLED_APPS=['raven.contrib.django']): client = DjangoTestClient(REMOTE_ADDR='127.0.0.1') client.handler = MockSentryMiddleware(MockClientHandler()) self.assertRaises(Exception, client.get, reverse('sentry-raise-exc')) assert len(self.raven.events) == 2 event = self.raven.events.pop(0) assert 'exception' in event exc = event['exception']['values'][-1] assert exc['type'] == 'Exception' assert exc['value'] == 'view exception' assert event['level'] == logging.ERROR assert event['message'] == 'Exception: view exception' event = self.raven.events.pop(0) assert 'exception' in event exc = event['exception']['values'][-1] assert exc['type'] == 'ValueError' assert exc['value'] == 'handler500' assert event['level'] == logging.ERROR assert event['message'] == 'ValueError: handler500' def test_view_middleware_exception(self): with Settings(MIDDLEWARE_CLASSES=['tests.contrib.django.middleware.BrokenViewMiddleware']): self.assertRaises(ImportError, self.client.get, reverse('sentry-raise-exc')) assert len(self.raven.events) == 1 event = self.raven.events.pop(0) assert 'exception' in event exc = event['exception']['values'][-1] assert exc['type'] == 'ImportError' assert exc['value'] == 'view' assert event['level'] == logging.ERROR assert event['message'] == 'ImportError: view' @pytest.mark.skipif(DJANGO_18, reason='Django 1.8+ not supported') def test_template_name_as_view(self): self.assertRaises(TemplateSyntaxError, self.client.get, reverse('sentry-template-exc')) assert len(self.raven.events) == 1 event = self.raven.events.pop(0) assert event['culprit'] == 'error.html' # def test_request_in_logging(self): # resp = self.client.get(reverse('sentry-log-request-exc')) # assert resp.status_code == 200 # assert len(self.raven.events) == 1 # event = self.raven.events.pop(0) # assert event['culprit'] == 'tests.contrib.django.views in logging_request_exc' # assert event['data']['META']['REMOTE_ADDR'] == '127.0.0.1' # TODO: Python bug #10805 @pytest.mark.skipif(not PY2, reason='Python 2') def test_record_none_exc_info(self): # sys.exc_info can return (None, None, None) if no exception is being # handled anywhere on the stack. See: # http://docs.python.org/library/sys.html#sys.exc_info record = logging.LogRecord( 'foo', logging.INFO, pathname=None, lineno=None, msg='test', args=(), exc_info=(None, None, None), ) handler = SentryHandler() handler.emit(record) assert len(self.raven.events) == 1 event = self.raven.events.pop(0) assert event['message'] == 'test' def test_404_middleware(self): with Settings(MIDDLEWARE_CLASSES=['raven.contrib.django.middleware.Sentry404CatchMiddleware']): resp = self.client.get('/non-existent-page') assert resp.status_code == 404 assert len(self.raven.events) == 1, [e['message'] for e in self.raven.events] event = self.raven.events.pop(0) assert event['level'] == logging.INFO assert event['logger'] == 'http404' assert 'request' in event http = event['request'] assert http['url'] == 'http://testserver/non-existent-page' assert http['method'] == 'GET' assert http['query_string'] == '' assert http['data'] is None def test_404_middleware_when_disabled(self): extra_settings = { 'MIDDLEWARE_CLASSES': ['raven.contrib.django.middleware.Sentry404CatchMiddleware'], 'SENTRY_CLIENT': 'tests.contrib.django.tests.DisabledTempStoreClient', } with Settings(**extra_settings): resp = self.client.get('/non-existent-page') assert resp.status_code == 404 assert self.raven.events == [] def test_invalid_client(self): extra_settings = { 'SENTRY_CLIENT': 'raven.contrib.django.DjangoClient', # default } # Should return fallback client (TempStoreClient) client = get_client('nonexistent.and.invalid') # client should be valid, and the same as with the next call. assert client is get_client() with Settings(**extra_settings): assert isinstance(get_client(), DjangoClient) def test_transport_specification(self): extra_settings = { 'SENTRY_TRANSPORT': 'raven.transport.HTTPTransport', 'SENTRY_DSN': 'http://*****:*****@example.com/1', } with Settings(**extra_settings): client = get_client(reset=True) assert type(client.remote.get_transport()) is HTTPTransport def test_response_error_id_middleware(self): # TODO: test with 500s with Settings(MIDDLEWARE_CLASSES=[ 'raven.contrib.django.middleware.SentryResponseErrorIdMiddleware', 'raven.contrib.django.middleware.Sentry404CatchMiddleware']): resp = self.client.get('/non-existent-page') assert resp.status_code == 404 headers = dict(resp.items()) assert 'X-Sentry-ID' in headers assert len(self.raven.events) == 1 event = self.raven.events.pop(0) assert event['event_id'] == headers['X-Sentry-ID'] def test_get_client(self): assert get_client() == get_client() assert get_client('raven.base.Client').__class__ == Client assert get_client() == self.raven assert get_client('%s.%s' % (type(self.raven).__module__, type(self.raven).__name__)) == self.raven assert get_client() == self.raven def test_raw_post_data_partial_read(self): v = '{"foo": "bar"}' request = make_request() request.environ.update({ 'wsgi.input': StringIO(v + '\r\n\r\n'), 'CONTENT_TYPE': 'application/octet-stream', 'CONTENT_LENGTH': len(v), }) request.read(1) self.raven.captureMessage(message='foo', request=request) assert len(self.raven.events) == 1 event = self.raven.events.pop(0) assert 'request' in event http = event['request'] assert http['method'] == 'POST' assert http['data'] == '<unavailable>' def test_read_post_data(self): request = make_request() request.POST = QueryDict("foo=bar&ham=spam") request.read(1) self.raven.captureMessage(message='foo', request=request) assert len(self.raven.events) == 1 event = self.raven.events.pop(0) assert 'request' in event http = event['request'] assert http['method'] == 'POST' assert http['data'] == {'foo': 'bar', 'ham': 'spam'} def test_request_capture(self): request = make_request() request.read(1) self.raven.captureMessage(message='foo', request=request) assert len(self.raven.events) == 1 event = self.raven.events.pop(0) assert 'request' in event http = event['request'] assert http['method'] == 'POST' assert http['data'] == '<unavailable>' assert 'headers' in http headers = http['headers'] assert 'Content-Type' in headers, headers.keys() assert headers['Content-Type'] == 'text/html' env = http['env'] assert 'SERVER_NAME' in env, env.keys() assert env['SERVER_NAME'] == 'testserver' assert 'SERVER_PORT' in env, env.keys() assert env['SERVER_PORT'] == '80' def test_marks_django_frames_correctly(self): self.assertRaises(TemplateSyntaxError, self.client.get, reverse('sentry-template-exc')) assert len(self.raven.events) == 1 event = self.raven.events.pop(0) frames = event['exception']['values'][-1]['stacktrace']['frames'] for frame in frames: if frame['module'].startswith('django.'): assert frame.get('in_app') is False def test_adds_site_to_tags(self): self.assertRaises(TemplateSyntaxError, self.client.get, reverse('sentry-template-exc')) assert len(self.raven.events) == 1 event = self.raven.events.pop(0) tags = event['tags'] assert 'site' in event['tags'] assert tags['site'] == 'example.com' def test_adds_site_to_tags_fallback(self): with Settings(SITE_ID=12345): # nonexistent site, should fallback to SITE_ID self.assertRaises(TemplateSyntaxError, self.client.get, reverse('sentry-template-exc')) assert len(self.raven.events) == 1 event = self.raven.events.pop(0) tags = event['tags'] assert 'site' in event['tags'] assert tags['site'] == 12345 def test_settings_site_overrides_contrib(self): self.raven.site = 'FOO' self.assertRaises(TemplateSyntaxError, self.client.get, reverse('sentry-template-exc')) assert len(self.raven.events) == 1 event = self.raven.events.pop(0) tags = event['tags'] assert 'site' in event['tags'] assert tags['site'] == 'FOO' @mock.patch.object(WSGIRequest, 'build_absolute_uri') def test_suspicious_operation_in_build_absolute_uri(self, build_absolute_uri): build_absolute_uri.side_effect = SuspiciousOperation() request = make_request() request.META['HTTP_HOST'] = 'example.com' result = self.raven.get_data_from_request(request) build_absolute_uri.assert_called_once_with() assert 'request' in result assert result['request']['url'] == 'http://example.com/'