diff options
author | Samir Shah <solaris.smoke@gmail.com> | 2017-07-13 07:09:18 +0300 |
---|---|---|
committer | Tim Graham <timograham@gmail.com> | 2018-05-04 20:55:03 -0400 |
commit | 10b44e45256ddda4258ae032b8d4725a3e3284e6 (patch) | |
tree | de7c8b159c5104d3da1a2b51a946d35404be07d6 /tests/logging_tests | |
parent | 2e1f674897e89bbc69a389696773aebfec601916 (diff) | |
download | django-10b44e45256ddda4258ae032b8d4725a3e3284e6.tar.gz |
Fixed #26688 -- Fixed HTTP request logging inconsistencies.
* Added logging of 500 responses for instantiated responses.
* Added logging of all 4xx and 5xx responses.
Diffstat (limited to 'tests/logging_tests')
-rw-r--r-- | tests/logging_tests/tests.py | 114 | ||||
-rw-r--r-- | tests/logging_tests/urls.py | 7 | ||||
-rw-r--r-- | tests/logging_tests/views.py | 38 |
3 files changed, 144 insertions, 15 deletions
diff --git a/tests/logging_tests/tests.py b/tests/logging_tests/tests.py index 0330fdccf5..e38a193693 100644 --- a/tests/logging_tests/tests.py +++ b/tests/logging_tests/tests.py @@ -6,15 +6,18 @@ from admin_scripts.tests import AdminScriptTestCase from django.conf import settings from django.core import mail +from django.core.exceptions import PermissionDenied from django.core.files.temp import NamedTemporaryFile from django.core.management import color +from django.http.multipartparser import MultiPartParserError from django.test import RequestFactory, SimpleTestCase, override_settings -from django.test.utils import LoggingCaptureMixin, patch_logger +from django.test.utils import LoggingCaptureMixin from django.utils.log import ( DEFAULT_LOGGING, AdminEmailHandler, CallbackFilter, RequireDebugFalse, RequireDebugTrue, ServerFormatter, ) +from . import views from .logconfig import MyEmailBackend # logging config prior to using filter with mail_admins @@ -106,16 +109,95 @@ class DefaultLoggingTests(SetupDefaultLoggingMixin, LoggingCaptureMixin, SimpleT self.assertEqual(self.logger_output.getvalue(), '') +class LoggingAssertionMixin(object): + + def assertLogsRequest(self, url, level, msg, status_code, logger='django.request', exc_class=None): + with self.assertLogs(logger, level) as cm: + try: + self.client.get(url) + except views.UncaughtException: + pass + self.assertEqual( + len(cm.records), 1, + "Wrong number of calls for logger %r in %r level." % (logger, level) + ) + record = cm.records[0] + self.assertEqual(record.getMessage(), msg) + self.assertEqual(record.status_code, status_code) + if exc_class: + self.assertIsNotNone(record.exc_info) + self.assertEqual(record.exc_info[0], exc_class) + + @override_settings(DEBUG=True, ROOT_URLCONF='logging_tests.urls') -class HandlerLoggingTests(SetupDefaultLoggingMixin, LoggingCaptureMixin, SimpleTestCase): +class HandlerLoggingTests(SetupDefaultLoggingMixin, LoggingAssertionMixin, LoggingCaptureMixin, SimpleTestCase): def test_page_found_no_warning(self): self.client.get('/innocent/') self.assertEqual(self.logger_output.getvalue(), '') + def test_redirect_no_warning(self): + self.client.get('/redirect/') + self.assertEqual(self.logger_output.getvalue(), '') + def test_page_not_found_warning(self): - self.client.get('/does_not_exist/') - self.assertEqual(self.logger_output.getvalue(), 'Not Found: /does_not_exist/\n') + self.assertLogsRequest( + url='/does_not_exist/', + level='WARNING', + status_code=404, + msg='Not Found: /does_not_exist/', + ) + + def test_page_not_found_raised(self): + self.assertLogsRequest( + url='/does_not_exist_raised/', + level='WARNING', + status_code=404, + msg='Not Found: /does_not_exist_raised/', + ) + + def test_uncaught_exception(self): + self.assertLogsRequest( + url='/uncaught_exception/', + level='ERROR', + status_code=500, + msg='Internal Server Error: /uncaught_exception/', + exc_class=views.UncaughtException, + ) + + def test_internal_server_error(self): + self.assertLogsRequest( + url='/internal_server_error/', + level='ERROR', + status_code=500, + msg='Internal Server Error: /internal_server_error/', + ) + + def test_internal_server_error_599(self): + self.assertLogsRequest( + url='/internal_server_error/?status=599', + level='ERROR', + status_code=599, + msg='Unknown Status Code: /internal_server_error/', + ) + + def test_permission_denied(self): + self.assertLogsRequest( + url='/permission_denied/', + level='WARNING', + status_code=403, + msg='Forbidden (Permission denied): /permission_denied/', + exc_class=PermissionDenied, + ) + + def test_multi_part_parser_error(self): + self.assertLogsRequest( + url='/multi_part_parser_error/', + level='WARNING', + status_code=400, + msg='Bad request (Unable to parse request body): /multi_part_parser_error/', + exc_class=MultiPartParserError, + ) @override_settings( @@ -401,19 +483,25 @@ class SetupConfigureLogging(SimpleTestCase): @override_settings(DEBUG=True, ROOT_URLCONF='logging_tests.urls') -class SecurityLoggerTest(SimpleTestCase): +class SecurityLoggerTest(LoggingAssertionMixin, SimpleTestCase): def test_suspicious_operation_creates_log_message(self): - with patch_logger('django.security.SuspiciousOperation', 'error') as calls: - self.client.get('/suspicious/') - self.assertEqual(len(calls), 1) - self.assertEqual(calls[0], 'dubious') + self.assertLogsRequest( + url='/suspicious/', + level='ERROR', + msg='dubious', + status_code=400, + logger='django.security.SuspiciousOperation', + ) def test_suspicious_operation_uses_sublogger(self): - with patch_logger('django.security.DisallowedHost', 'error') as calls: - self.client.get('/suspicious_spec/') - self.assertEqual(len(calls), 1) - self.assertEqual(calls[0], 'dubious') + self.assertLogsRequest( + url='/suspicious_spec/', + level='ERROR', + msg='dubious', + status_code=400, + logger='django.security.DisallowedHost', + ) @override_settings( ADMINS=[('admin', 'admin@example.com')], diff --git a/tests/logging_tests/urls.py b/tests/logging_tests/urls.py index fa2c0fcd02..d5cdb7c17d 100644 --- a/tests/logging_tests/urls.py +++ b/tests/logging_tests/urls.py @@ -1,9 +1,16 @@ from django.conf.urls import url +from django.urls import path from . import views urlpatterns = [ url(r'^innocent/$', views.innocent), + path('redirect/', views.redirect), url(r'^suspicious/$', views.suspicious), url(r'^suspicious_spec/$', views.suspicious_spec), + path('internal_server_error/', views.internal_server_error), + path('uncaught_exception/', views.uncaught_exception), + path('permission_denied/', views.permission_denied), + path('multi_part_parser_error/', views.multi_part_parser_error), + path('does_not_exist_raised/', views.does_not_exist_raised), ] diff --git a/tests/logging_tests/views.py b/tests/logging_tests/views.py index cb7112e435..a40a517233 100644 --- a/tests/logging_tests/views.py +++ b/tests/logging_tests/views.py @@ -1,14 +1,48 @@ -from django.core.exceptions import DisallowedHost, SuspiciousOperation -from django.http import HttpResponse +from django.core.exceptions import ( + DisallowedHost, PermissionDenied, SuspiciousOperation, +) +from django.http import ( + Http404, HttpResponse, HttpResponseRedirect, HttpResponseServerError, +) +from django.http.multipartparser import MultiPartParserError def innocent(request): return HttpResponse('innocent') +def redirect(request): + return HttpResponseRedirect('/') + + def suspicious(request): raise SuspiciousOperation('dubious') def suspicious_spec(request): raise DisallowedHost('dubious') + + +class UncaughtException(Exception): + pass + + +def uncaught_exception(request): + raise UncaughtException('Uncaught exception') + + +def internal_server_error(request): + status = request.GET.get('status', 500) + return HttpResponseServerError('Server Error', status=int(status)) + + +def permission_denied(request): + raise PermissionDenied() + + +def multi_part_parser_error(request): + raise MultiPartParserError('parsing error') + + +def does_not_exist_raised(request): + raise Http404('Not Found') |