2022-07-19 15:45:11 +08:00
|
|
|
import multiprocessing
|
2014-01-20 10:45:21 +08:00
|
|
|
import sys
|
2017-01-07 19:11:46 +08:00
|
|
|
from io import StringIO
|
2022-07-19 15:45:11 +08:00
|
|
|
from unittest import skipIf
|
2014-01-20 10:45:21 +08:00
|
|
|
|
|
|
|
from django.apps import apps
|
|
|
|
from django.core import checks
|
2014-01-23 03:09:02 +08:00
|
|
|
from django.core.checks import Error, Warning
|
2021-03-16 23:41:27 +08:00
|
|
|
from django.core.checks.messages import CheckMessage
|
2014-01-20 10:45:21 +08:00
|
|
|
from django.core.checks.registry import CheckRegistry
|
|
|
|
from django.core.management import call_command
|
2015-01-28 20:35:27 +08:00
|
|
|
from django.core.management.base import CommandError
|
2014-10-14 21:10:27 +08:00
|
|
|
from django.db import models
|
2015-04-18 05:38:20 +08:00
|
|
|
from django.test import SimpleTestCase
|
2015-11-17 13:39:28 +08:00
|
|
|
from django.test.utils import isolate_apps, override_settings, override_system_checks
|
2014-01-20 10:45:21 +08:00
|
|
|
|
2016-03-18 22:24:13 +08:00
|
|
|
from .models import SimpleModel, my_check
|
2014-01-20 10:45:21 +08:00
|
|
|
|
|
|
|
|
2017-01-19 15:39:46 +08:00
|
|
|
class DummyObj:
|
2014-01-20 10:45:21 +08:00
|
|
|
def __repr__(self):
|
|
|
|
return "obj"
|
|
|
|
|
|
|
|
|
2015-04-18 05:38:20 +08:00
|
|
|
class SystemCheckFrameworkTests(SimpleTestCase):
|
2014-01-20 10:45:21 +08:00
|
|
|
def test_register_and_run_checks(self):
|
|
|
|
def f(**kwargs):
|
|
|
|
calls[0] += 1
|
|
|
|
return [1, 2, 3]
|
2014-11-05 14:01:49 +08:00
|
|
|
|
|
|
|
def f2(**kwargs):
|
2017-12-29 04:07:29 +08:00
|
|
|
return [4]
|
2014-11-05 14:01:49 +08:00
|
|
|
|
|
|
|
def f3(**kwargs):
|
2017-12-29 04:07:29 +08:00
|
|
|
return [5]
|
2014-11-05 14:01:49 +08:00
|
|
|
|
|
|
|
calls = [0]
|
|
|
|
|
|
|
|
# test register as decorator
|
|
|
|
registry = CheckRegistry()
|
|
|
|
registry.register()(f)
|
|
|
|
registry.register("tag1", "tag2")(f2)
|
|
|
|
registry.register("tag2", deploy=True)(f3)
|
|
|
|
|
|
|
|
# test register as function
|
|
|
|
registry2 = CheckRegistry()
|
|
|
|
registry2.register(f)
|
|
|
|
registry2.register(f2, "tag1", "tag2")
|
|
|
|
registry2.register(f3, "tag2", deploy=True)
|
|
|
|
|
|
|
|
# check results
|
2014-01-20 10:45:21 +08:00
|
|
|
errors = registry.run_checks()
|
2014-11-05 14:01:49 +08:00
|
|
|
errors2 = registry2.run_checks()
|
|
|
|
self.assertEqual(errors, errors2)
|
|
|
|
self.assertEqual(sorted(errors), [1, 2, 3, 4])
|
|
|
|
self.assertEqual(calls[0], 2)
|
|
|
|
|
|
|
|
errors = registry.run_checks(tags=["tag1"])
|
|
|
|
errors2 = registry2.run_checks(tags=["tag1"])
|
|
|
|
self.assertEqual(errors, errors2)
|
|
|
|
self.assertEqual(sorted(errors), [4])
|
|
|
|
|
|
|
|
errors = registry.run_checks(
|
|
|
|
tags=["tag1", "tag2"], include_deployment_checks=True
|
|
|
|
)
|
|
|
|
errors2 = registry2.run_checks(
|
|
|
|
tags=["tag1", "tag2"], include_deployment_checks=True
|
|
|
|
)
|
|
|
|
self.assertEqual(errors, errors2)
|
|
|
|
self.assertEqual(sorted(errors), [4, 5])
|
2014-01-20 10:45:21 +08:00
|
|
|
|
2020-12-14 00:56:04 +08:00
|
|
|
def test_register_no_kwargs_error(self):
|
|
|
|
registry = CheckRegistry()
|
|
|
|
msg = "Check functions must accept keyword arguments (**kwargs)."
|
|
|
|
with self.assertRaisesMessage(TypeError, msg):
|
2022-02-04 03:24:19 +08:00
|
|
|
|
2020-12-14 00:56:04 +08:00
|
|
|
@registry.register
|
|
|
|
def no_kwargs(app_configs, databases):
|
|
|
|
pass
|
|
|
|
|
2021-03-16 23:41:27 +08:00
|
|
|
def test_register_run_checks_non_iterable(self):
|
|
|
|
registry = CheckRegistry()
|
|
|
|
|
|
|
|
@registry.register
|
|
|
|
def return_non_iterable(**kwargs):
|
|
|
|
return Error("Message")
|
|
|
|
|
|
|
|
msg = (
|
|
|
|
"The function %r did not return a list. All functions registered "
|
|
|
|
"with the checks registry must return a list." % return_non_iterable
|
|
|
|
)
|
|
|
|
with self.assertRaisesMessage(TypeError, msg):
|
|
|
|
registry.run_checks()
|
|
|
|
|
2014-01-20 10:45:21 +08:00
|
|
|
|
2015-04-18 05:38:20 +08:00
|
|
|
class MessageTests(SimpleTestCase):
|
2014-01-20 10:45:21 +08:00
|
|
|
def test_printing(self):
|
|
|
|
e = Error("Message", hint="Hint", obj=DummyObj())
|
|
|
|
expected = "obj: Message\n\tHINT: Hint"
|
2017-01-24 19:22:42 +08:00
|
|
|
self.assertEqual(str(e), expected)
|
2014-01-20 10:45:21 +08:00
|
|
|
|
|
|
|
def test_printing_no_hint(self):
|
2016-02-13 00:36:46 +08:00
|
|
|
e = Error("Message", obj=DummyObj())
|
2014-01-20 10:45:21 +08:00
|
|
|
expected = "obj: Message"
|
2017-01-24 19:22:42 +08:00
|
|
|
self.assertEqual(str(e), expected)
|
2014-01-20 10:45:21 +08:00
|
|
|
|
|
|
|
def test_printing_no_object(self):
|
2016-02-13 00:36:46 +08:00
|
|
|
e = Error("Message", hint="Hint")
|
2014-01-20 10:45:21 +08:00
|
|
|
expected = "?: Message\n\tHINT: Hint"
|
2017-01-24 19:22:42 +08:00
|
|
|
self.assertEqual(str(e), expected)
|
2014-01-20 10:45:21 +08:00
|
|
|
|
|
|
|
def test_printing_with_given_id(self):
|
|
|
|
e = Error("Message", hint="Hint", obj=DummyObj(), id="ID")
|
|
|
|
expected = "obj: (ID) Message\n\tHINT: Hint"
|
2017-01-24 19:22:42 +08:00
|
|
|
self.assertEqual(str(e), expected)
|
2014-01-20 10:45:21 +08:00
|
|
|
|
|
|
|
def test_printing_field_error(self):
|
|
|
|
field = SimpleModel._meta.get_field("field")
|
2016-02-13 00:36:46 +08:00
|
|
|
e = Error("Error", obj=field)
|
2014-01-20 10:45:21 +08:00
|
|
|
expected = "check_framework.SimpleModel.field: Error"
|
2017-01-24 19:22:42 +08:00
|
|
|
self.assertEqual(str(e), expected)
|
2014-01-20 10:45:21 +08:00
|
|
|
|
|
|
|
def test_printing_model_error(self):
|
2016-02-13 00:36:46 +08:00
|
|
|
e = Error("Error", obj=SimpleModel)
|
2014-01-20 10:45:21 +08:00
|
|
|
expected = "check_framework.SimpleModel: Error"
|
2017-01-24 19:22:42 +08:00
|
|
|
self.assertEqual(str(e), expected)
|
2014-01-20 10:45:21 +08:00
|
|
|
|
|
|
|
def test_printing_manager_error(self):
|
|
|
|
manager = SimpleModel.manager
|
2016-02-13 00:36:46 +08:00
|
|
|
e = Error("Error", obj=manager)
|
2014-01-20 10:45:21 +08:00
|
|
|
expected = "check_framework.SimpleModel.manager: Error"
|
2017-01-24 19:22:42 +08:00
|
|
|
self.assertEqual(str(e), expected)
|
2014-01-20 10:45:21 +08:00
|
|
|
|
2016-08-05 21:18:12 +08:00
|
|
|
def test_equal_to_self(self):
|
|
|
|
e = Error("Error", obj=SimpleModel)
|
|
|
|
self.assertEqual(e, e)
|
|
|
|
|
|
|
|
def test_equal_to_same_constructed_check(self):
|
|
|
|
e1 = Error("Error", obj=SimpleModel)
|
|
|
|
e2 = Error("Error", obj=SimpleModel)
|
|
|
|
self.assertEqual(e1, e2)
|
|
|
|
|
|
|
|
def test_not_equal_to_different_constructed_check(self):
|
|
|
|
e1 = Error("Error", obj=SimpleModel)
|
|
|
|
e2 = Error("Error2", obj=SimpleModel)
|
|
|
|
self.assertNotEqual(e1, e2)
|
|
|
|
|
2016-08-05 21:18:12 +08:00
|
|
|
def test_not_equal_to_non_check(self):
|
|
|
|
e = Error("Error", obj=DummyObj())
|
|
|
|
self.assertNotEqual(e, "a string")
|
|
|
|
|
2021-03-16 23:41:27 +08:00
|
|
|
def test_invalid_level(self):
|
|
|
|
msg = "The first argument should be level."
|
|
|
|
with self.assertRaisesMessage(TypeError, msg):
|
|
|
|
CheckMessage("ERROR", "Message")
|
|
|
|
|
2014-01-20 10:45:21 +08:00
|
|
|
|
|
|
|
def simple_system_check(**kwargs):
|
|
|
|
simple_system_check.kwargs = kwargs
|
|
|
|
return []
|
|
|
|
|
|
|
|
|
|
|
|
def tagged_system_check(**kwargs):
|
|
|
|
tagged_system_check.kwargs = kwargs
|
2015-10-05 02:16:12 +08:00
|
|
|
return [checks.Warning("System Check")]
|
2016-11-13 01:11:23 +08:00
|
|
|
|
|
|
|
|
2014-01-20 10:45:21 +08:00
|
|
|
tagged_system_check.tags = ["simpletag"]
|
|
|
|
|
|
|
|
|
2014-09-13 02:50:36 +08:00
|
|
|
def deployment_system_check(**kwargs):
|
|
|
|
deployment_system_check.kwargs = kwargs
|
|
|
|
return [checks.Warning("Deployment Check")]
|
2016-11-13 01:11:23 +08:00
|
|
|
|
|
|
|
|
2014-09-13 02:50:36 +08:00
|
|
|
deployment_system_check.tags = ["deploymenttag"]
|
|
|
|
|
|
|
|
|
2015-04-18 05:38:20 +08:00
|
|
|
class CheckCommandTests(SimpleTestCase):
|
2014-01-20 10:45:21 +08:00
|
|
|
def setUp(self):
|
|
|
|
simple_system_check.kwargs = None
|
|
|
|
tagged_system_check.kwargs = None
|
|
|
|
self.old_stdout, self.old_stderr = sys.stdout, sys.stderr
|
|
|
|
sys.stdout, sys.stderr = StringIO(), StringIO()
|
|
|
|
|
|
|
|
def tearDown(self):
|
|
|
|
sys.stdout, sys.stderr = self.old_stdout, self.old_stderr
|
|
|
|
|
|
|
|
@override_system_checks([simple_system_check, tagged_system_check])
|
|
|
|
def test_simple_call(self):
|
|
|
|
call_command("check")
|
2020-02-07 15:46:13 +08:00
|
|
|
self.assertEqual(
|
|
|
|
simple_system_check.kwargs, {"app_configs": None, "databases": None}
|
|
|
|
)
|
|
|
|
self.assertEqual(
|
|
|
|
tagged_system_check.kwargs, {"app_configs": None, "databases": None}
|
|
|
|
)
|
2014-01-20 10:45:21 +08:00
|
|
|
|
|
|
|
@override_system_checks([simple_system_check, tagged_system_check])
|
|
|
|
def test_given_app(self):
|
|
|
|
call_command("check", "auth", "admin")
|
|
|
|
auth_config = apps.get_app_config("auth")
|
|
|
|
admin_config = apps.get_app_config("admin")
|
2020-02-07 15:46:13 +08:00
|
|
|
self.assertEqual(
|
|
|
|
simple_system_check.kwargs,
|
|
|
|
{"app_configs": [auth_config, admin_config], "databases": None},
|
|
|
|
)
|
|
|
|
self.assertEqual(
|
|
|
|
tagged_system_check.kwargs,
|
|
|
|
{"app_configs": [auth_config, admin_config], "databases": None},
|
|
|
|
)
|
2014-01-20 10:45:21 +08:00
|
|
|
|
|
|
|
@override_system_checks([simple_system_check, tagged_system_check])
|
|
|
|
def test_given_tag(self):
|
|
|
|
call_command("check", tags=["simpletag"])
|
2016-06-17 02:19:18 +08:00
|
|
|
self.assertIsNone(simple_system_check.kwargs)
|
2020-02-07 15:46:13 +08:00
|
|
|
self.assertEqual(
|
|
|
|
tagged_system_check.kwargs, {"app_configs": None, "databases": None}
|
|
|
|
)
|
2014-01-20 10:45:21 +08:00
|
|
|
|
|
|
|
@override_system_checks([simple_system_check, tagged_system_check])
|
|
|
|
def test_invalid_tag(self):
|
2017-05-29 03:37:21 +08:00
|
|
|
msg = 'There is no system check with the "missingtag" tag.'
|
|
|
|
with self.assertRaisesMessage(CommandError, msg):
|
2016-01-17 19:26:39 +08:00
|
|
|
call_command("check", tags=["missingtag"])
|
2014-01-20 10:45:21 +08:00
|
|
|
|
2014-04-10 21:43:55 +08:00
|
|
|
@override_system_checks([simple_system_check])
|
|
|
|
def test_list_tags_empty(self):
|
|
|
|
call_command("check", list_tags=True)
|
|
|
|
self.assertEqual("\n", sys.stdout.getvalue())
|
|
|
|
|
|
|
|
@override_system_checks([tagged_system_check])
|
|
|
|
def test_list_tags(self):
|
|
|
|
call_command("check", list_tags=True)
|
|
|
|
self.assertEqual("simpletag\n", sys.stdout.getvalue())
|
|
|
|
|
2014-09-13 02:50:36 +08:00
|
|
|
@override_system_checks(
|
|
|
|
[tagged_system_check], deployment_checks=[deployment_system_check]
|
|
|
|
)
|
|
|
|
def test_list_deployment_check_omitted(self):
|
|
|
|
call_command("check", list_tags=True)
|
|
|
|
self.assertEqual("simpletag\n", sys.stdout.getvalue())
|
|
|
|
|
|
|
|
@override_system_checks(
|
|
|
|
[tagged_system_check], deployment_checks=[deployment_system_check]
|
|
|
|
)
|
|
|
|
def test_list_deployment_check_included(self):
|
|
|
|
call_command("check", deploy=True, list_tags=True)
|
|
|
|
self.assertEqual("deploymenttag\nsimpletag\n", sys.stdout.getvalue())
|
|
|
|
|
|
|
|
@override_system_checks(
|
|
|
|
[tagged_system_check], deployment_checks=[deployment_system_check]
|
|
|
|
)
|
|
|
|
def test_tags_deployment_check_omitted(self):
|
|
|
|
msg = 'There is no system check with the "deploymenttag" tag.'
|
|
|
|
with self.assertRaisesMessage(CommandError, msg):
|
|
|
|
call_command("check", tags=["deploymenttag"])
|
|
|
|
|
|
|
|
@override_system_checks(
|
|
|
|
[tagged_system_check], deployment_checks=[deployment_system_check]
|
|
|
|
)
|
|
|
|
def test_tags_deployment_check_included(self):
|
|
|
|
call_command("check", deploy=True, tags=["deploymenttag"])
|
|
|
|
self.assertIn("Deployment Check", sys.stderr.getvalue())
|
|
|
|
|
2015-10-05 02:16:12 +08:00
|
|
|
@override_system_checks([tagged_system_check])
|
|
|
|
def test_fail_level(self):
|
|
|
|
with self.assertRaises(CommandError):
|
|
|
|
call_command("check", fail_level="WARNING")
|
|
|
|
|
2014-01-20 10:45:21 +08:00
|
|
|
|
2014-01-23 03:09:02 +08:00
|
|
|
def custom_error_system_check(app_configs, **kwargs):
|
2016-02-13 00:36:46 +08:00
|
|
|
return [Error("Error", id="myerrorcheck.E001")]
|
2014-01-23 03:09:02 +08:00
|
|
|
|
|
|
|
|
|
|
|
def custom_warning_system_check(app_configs, **kwargs):
|
2016-02-13 00:36:46 +08:00
|
|
|
return [Warning("Warning", id="mywarningcheck.E001")]
|
2014-01-20 10:45:21 +08:00
|
|
|
|
|
|
|
|
2015-04-18 05:38:20 +08:00
|
|
|
class SilencingCheckTests(SimpleTestCase):
|
2014-01-20 10:45:21 +08:00
|
|
|
def setUp(self):
|
|
|
|
self.old_stdout, self.old_stderr = sys.stdout, sys.stderr
|
2014-01-23 03:09:02 +08:00
|
|
|
self.stdout, self.stderr = StringIO(), StringIO()
|
|
|
|
sys.stdout, sys.stderr = self.stdout, self.stderr
|
2014-01-20 10:45:21 +08:00
|
|
|
|
|
|
|
def tearDown(self):
|
|
|
|
sys.stdout, sys.stderr = self.old_stdout, self.old_stderr
|
|
|
|
|
2014-01-23 03:09:02 +08:00
|
|
|
@override_settings(SILENCED_SYSTEM_CHECKS=["myerrorcheck.E001"])
|
|
|
|
@override_system_checks([custom_error_system_check])
|
|
|
|
def test_silenced_error(self):
|
|
|
|
out = StringIO()
|
|
|
|
err = StringIO()
|
2016-06-28 23:21:26 +08:00
|
|
|
call_command("check", stdout=out, stderr=err)
|
2015-08-27 03:47:41 +08:00
|
|
|
self.assertEqual(
|
|
|
|
out.getvalue(), "System check identified no issues (1 silenced).\n"
|
|
|
|
)
|
|
|
|
self.assertEqual(err.getvalue(), "")
|
2014-01-23 03:09:02 +08:00
|
|
|
|
|
|
|
@override_settings(SILENCED_SYSTEM_CHECKS=["mywarningcheck.E001"])
|
|
|
|
@override_system_checks([custom_warning_system_check])
|
|
|
|
def test_silenced_warning(self):
|
|
|
|
out = StringIO()
|
|
|
|
err = StringIO()
|
2016-06-28 23:21:26 +08:00
|
|
|
call_command("check", stdout=out, stderr=err)
|
2014-01-23 03:09:02 +08:00
|
|
|
self.assertEqual(
|
|
|
|
out.getvalue(), "System check identified no issues (1 silenced).\n"
|
|
|
|
)
|
|
|
|
self.assertEqual(err.getvalue(), "")
|
2014-10-14 21:10:27 +08:00
|
|
|
|
|
|
|
|
2015-11-17 13:39:28 +08:00
|
|
|
class CheckFrameworkReservedNamesTests(SimpleTestCase):
|
|
|
|
@isolate_apps("check_framework", kwarg_name="apps")
|
|
|
|
@override_system_checks([checks.model_checks.check_all_models])
|
|
|
|
def test_model_check_method_not_shadowed(self, apps):
|
2014-10-14 21:10:27 +08:00
|
|
|
class ModelWithAttributeCalledCheck(models.Model):
|
|
|
|
check = 42
|
|
|
|
|
|
|
|
class ModelWithFieldCalledCheck(models.Model):
|
|
|
|
check = models.IntegerField()
|
|
|
|
|
|
|
|
class ModelWithRelatedManagerCalledCheck(models.Model):
|
|
|
|
pass
|
|
|
|
|
|
|
|
class ModelWithDescriptorCalledCheck(models.Model):
|
2015-07-22 22:43:21 +08:00
|
|
|
check = models.ForeignKey(
|
|
|
|
ModelWithRelatedManagerCalledCheck, models.CASCADE
|
|
|
|
)
|
|
|
|
article = models.ForeignKey(
|
|
|
|
ModelWithRelatedManagerCalledCheck,
|
|
|
|
models.CASCADE,
|
|
|
|
related_name="check",
|
|
|
|
)
|
2014-10-14 21:10:27 +08:00
|
|
|
|
2015-11-17 13:39:28 +08:00
|
|
|
errors = checks.run_checks(app_configs=apps.get_app_configs())
|
2014-10-14 21:10:27 +08:00
|
|
|
expected = [
|
|
|
|
Error(
|
|
|
|
"The 'ModelWithAttributeCalledCheck.check()' class method is "
|
|
|
|
"currently overridden by 42.",
|
|
|
|
obj=ModelWithAttributeCalledCheck,
|
|
|
|
id="models.E020",
|
|
|
|
),
|
2021-06-09 22:55:22 +08:00
|
|
|
Error(
|
|
|
|
"The 'ModelWithFieldCalledCheck.check()' class method is "
|
|
|
|
"currently overridden by %r." % ModelWithFieldCalledCheck.check,
|
|
|
|
obj=ModelWithFieldCalledCheck,
|
|
|
|
id="models.E020",
|
|
|
|
),
|
2014-10-14 21:10:27 +08:00
|
|
|
Error(
|
|
|
|
"The 'ModelWithRelatedManagerCalledCheck.check()' class method is "
|
|
|
|
"currently overridden by %r."
|
|
|
|
% ModelWithRelatedManagerCalledCheck.check,
|
|
|
|
obj=ModelWithRelatedManagerCalledCheck,
|
|
|
|
id="models.E020",
|
|
|
|
),
|
|
|
|
Error(
|
|
|
|
"The 'ModelWithDescriptorCalledCheck.check()' class method is "
|
|
|
|
"currently overridden by %r." % ModelWithDescriptorCalledCheck.check,
|
|
|
|
obj=ModelWithDescriptorCalledCheck,
|
|
|
|
id="models.E020",
|
|
|
|
),
|
|
|
|
]
|
2014-09-09 01:38:07 +08:00
|
|
|
self.assertEqual(errors, expected)
|
2016-03-18 22:24:13 +08:00
|
|
|
|
|
|
|
|
2022-07-19 15:45:11 +08:00
|
|
|
@skipIf(
|
|
|
|
multiprocessing.get_start_method() == "spawn",
|
|
|
|
"Spawning reimports modules, overwriting my_check.did_run to False, making this "
|
|
|
|
"test useless.",
|
|
|
|
)
|
2016-03-18 22:24:13 +08:00
|
|
|
class ChecksRunDuringTests(SimpleTestCase):
|
2022-02-13 04:40:12 +08:00
|
|
|
databases = "__all__"
|
|
|
|
|
2016-03-18 22:24:13 +08:00
|
|
|
def test_registered_check_did_run(self):
|
|
|
|
self.assertTrue(my_check.did_run)
|