|
@@ -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')],
|