tests.py 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455
  1. import os
  2. import sys
  3. import unittest
  4. from types import ModuleType
  5. from unittest import mock
  6. from django.conf import ENVIRONMENT_VARIABLE, LazySettings, Settings, settings
  7. from django.core.exceptions import ImproperlyConfigured
  8. from django.http import HttpRequest
  9. from django.test import (
  10. SimpleTestCase, TestCase, TransactionTestCase, modify_settings,
  11. override_settings, signals,
  12. )
  13. from django.test.utils import requires_tz_support
  14. @modify_settings(ITEMS={
  15. 'prepend': ['b'],
  16. 'append': ['d'],
  17. 'remove': ['a', 'e']
  18. })
  19. @override_settings(ITEMS=['a', 'c', 'e'], ITEMS_OUTER=[1, 2, 3], TEST='override', TEST_OUTER='outer')
  20. class FullyDecoratedTranTestCase(TransactionTestCase):
  21. available_apps = []
  22. def test_override(self):
  23. self.assertEqual(settings.ITEMS, ['b', 'c', 'd'])
  24. self.assertEqual(settings.ITEMS_OUTER, [1, 2, 3])
  25. self.assertEqual(settings.TEST, 'override')
  26. self.assertEqual(settings.TEST_OUTER, 'outer')
  27. @modify_settings(ITEMS={
  28. 'append': ['e', 'f'],
  29. 'prepend': ['a'],
  30. 'remove': ['d', 'c'],
  31. })
  32. def test_method_list_override(self):
  33. self.assertEqual(settings.ITEMS, ['a', 'b', 'e', 'f'])
  34. self.assertEqual(settings.ITEMS_OUTER, [1, 2, 3])
  35. @modify_settings(ITEMS={
  36. 'append': ['b'],
  37. 'prepend': ['d'],
  38. 'remove': ['a', 'c', 'e'],
  39. })
  40. def test_method_list_override_no_ops(self):
  41. self.assertEqual(settings.ITEMS, ['b', 'd'])
  42. @modify_settings(ITEMS={
  43. 'append': 'e',
  44. 'prepend': 'a',
  45. 'remove': 'c',
  46. })
  47. def test_method_list_override_strings(self):
  48. self.assertEqual(settings.ITEMS, ['a', 'b', 'd', 'e'])
  49. @modify_settings(ITEMS={'remove': ['b', 'd']})
  50. @modify_settings(ITEMS={'append': ['b'], 'prepend': ['d']})
  51. def test_method_list_override_nested_order(self):
  52. self.assertEqual(settings.ITEMS, ['d', 'c', 'b'])
  53. @override_settings(TEST='override2')
  54. def test_method_override(self):
  55. self.assertEqual(settings.TEST, 'override2')
  56. self.assertEqual(settings.TEST_OUTER, 'outer')
  57. def test_decorated_testcase_name(self):
  58. self.assertEqual(FullyDecoratedTranTestCase.__name__, 'FullyDecoratedTranTestCase')
  59. def test_decorated_testcase_module(self):
  60. self.assertEqual(FullyDecoratedTranTestCase.__module__, __name__)
  61. @modify_settings(ITEMS={
  62. 'prepend': ['b'],
  63. 'append': ['d'],
  64. 'remove': ['a', 'e']
  65. })
  66. @override_settings(ITEMS=['a', 'c', 'e'], TEST='override')
  67. class FullyDecoratedTestCase(TestCase):
  68. def test_override(self):
  69. self.assertEqual(settings.ITEMS, ['b', 'c', 'd'])
  70. self.assertEqual(settings.TEST, 'override')
  71. @modify_settings(ITEMS={
  72. 'append': 'e',
  73. 'prepend': 'a',
  74. 'remove': 'c',
  75. })
  76. @override_settings(TEST='override2')
  77. def test_method_override(self):
  78. self.assertEqual(settings.ITEMS, ['a', 'b', 'd', 'e'])
  79. self.assertEqual(settings.TEST, 'override2')
  80. class ClassDecoratedTestCaseSuper(TestCase):
  81. """
  82. Dummy class for testing max recursion error in child class call to
  83. super(). Refs #17011.
  84. """
  85. def test_max_recursion_error(self):
  86. pass
  87. @override_settings(TEST='override')
  88. class ClassDecoratedTestCase(ClassDecoratedTestCaseSuper):
  89. @classmethod
  90. def setUpClass(cls):
  91. super().setUpClass()
  92. cls.foo = getattr(settings, 'TEST', 'BUG')
  93. def test_override(self):
  94. self.assertEqual(settings.TEST, 'override')
  95. def test_setupclass_override(self):
  96. """Settings are overridden within setUpClass (#21281)."""
  97. self.assertEqual(self.foo, 'override')
  98. @override_settings(TEST='override2')
  99. def test_method_override(self):
  100. self.assertEqual(settings.TEST, 'override2')
  101. def test_max_recursion_error(self):
  102. """
  103. Overriding a method on a super class and then calling that method on
  104. the super class should not trigger infinite recursion. See #17011.
  105. """
  106. super().test_max_recursion_error()
  107. @modify_settings(ITEMS={'append': 'mother'})
  108. @override_settings(ITEMS=['father'], TEST='override-parent')
  109. class ParentDecoratedTestCase(TestCase):
  110. pass
  111. @modify_settings(ITEMS={'append': ['child']})
  112. @override_settings(TEST='override-child')
  113. class ChildDecoratedTestCase(ParentDecoratedTestCase):
  114. def test_override_settings_inheritance(self):
  115. self.assertEqual(settings.ITEMS, ['father', 'mother', 'child'])
  116. self.assertEqual(settings.TEST, 'override-child')
  117. class SettingsTests(SimpleTestCase):
  118. def setUp(self):
  119. self.testvalue = None
  120. signals.setting_changed.connect(self.signal_callback)
  121. def tearDown(self):
  122. signals.setting_changed.disconnect(self.signal_callback)
  123. def signal_callback(self, sender, setting, value, **kwargs):
  124. if setting == 'TEST':
  125. self.testvalue = value
  126. def test_override(self):
  127. settings.TEST = 'test'
  128. self.assertEqual('test', settings.TEST)
  129. with self.settings(TEST='override'):
  130. self.assertEqual('override', settings.TEST)
  131. self.assertEqual('test', settings.TEST)
  132. del settings.TEST
  133. def test_override_change(self):
  134. settings.TEST = 'test'
  135. self.assertEqual('test', settings.TEST)
  136. with self.settings(TEST='override'):
  137. self.assertEqual('override', settings.TEST)
  138. settings.TEST = 'test2'
  139. self.assertEqual('test', settings.TEST)
  140. del settings.TEST
  141. def test_override_doesnt_leak(self):
  142. with self.assertRaises(AttributeError):
  143. getattr(settings, 'TEST')
  144. with self.settings(TEST='override'):
  145. self.assertEqual('override', settings.TEST)
  146. settings.TEST = 'test'
  147. with self.assertRaises(AttributeError):
  148. getattr(settings, 'TEST')
  149. @override_settings(TEST='override')
  150. def test_decorator(self):
  151. self.assertEqual('override', settings.TEST)
  152. def test_context_manager(self):
  153. with self.assertRaises(AttributeError):
  154. getattr(settings, 'TEST')
  155. override = override_settings(TEST='override')
  156. with self.assertRaises(AttributeError):
  157. getattr(settings, 'TEST')
  158. override.enable()
  159. self.assertEqual('override', settings.TEST)
  160. override.disable()
  161. with self.assertRaises(AttributeError):
  162. getattr(settings, 'TEST')
  163. def test_class_decorator(self):
  164. # SimpleTestCase can be decorated by override_settings, but not ut.TestCase
  165. class SimpleTestCaseSubclass(SimpleTestCase):
  166. pass
  167. class UnittestTestCaseSubclass(unittest.TestCase):
  168. pass
  169. decorated = override_settings(TEST='override')(SimpleTestCaseSubclass)
  170. self.assertIsInstance(decorated, type)
  171. self.assertTrue(issubclass(decorated, SimpleTestCase))
  172. with self.assertRaisesMessage(Exception, "Only subclasses of Django SimpleTestCase"):
  173. decorated = override_settings(TEST='override')(UnittestTestCaseSubclass)
  174. def test_signal_callback_context_manager(self):
  175. with self.assertRaises(AttributeError):
  176. getattr(settings, 'TEST')
  177. with self.settings(TEST='override'):
  178. self.assertEqual(self.testvalue, 'override')
  179. self.assertIsNone(self.testvalue)
  180. @override_settings(TEST='override')
  181. def test_signal_callback_decorator(self):
  182. self.assertEqual(self.testvalue, 'override')
  183. #
  184. # Regression tests for #10130: deleting settings.
  185. #
  186. def test_settings_delete(self):
  187. settings.TEST = 'test'
  188. self.assertEqual('test', settings.TEST)
  189. del settings.TEST
  190. msg = "'Settings' object has no attribute 'TEST'"
  191. with self.assertRaisesMessage(AttributeError, msg):
  192. getattr(settings, 'TEST')
  193. def test_settings_delete_wrapped(self):
  194. with self.assertRaisesMessage(TypeError, "can't delete _wrapped."):
  195. delattr(settings, '_wrapped')
  196. def test_override_settings_delete(self):
  197. """
  198. Allow deletion of a setting in an overridden settings set (#18824)
  199. """
  200. previous_i18n = settings.USE_I18N
  201. previous_l10n = settings.USE_L10N
  202. with self.settings(USE_I18N=False):
  203. del settings.USE_I18N
  204. with self.assertRaises(AttributeError):
  205. getattr(settings, 'USE_I18N')
  206. # Should also work for a non-overridden setting
  207. del settings.USE_L10N
  208. with self.assertRaises(AttributeError):
  209. getattr(settings, 'USE_L10N')
  210. self.assertNotIn('USE_I18N', dir(settings))
  211. self.assertNotIn('USE_L10N', dir(settings))
  212. self.assertEqual(settings.USE_I18N, previous_i18n)
  213. self.assertEqual(settings.USE_L10N, previous_l10n)
  214. def test_override_settings_nested(self):
  215. """
  216. override_settings uses the actual _wrapped attribute at
  217. runtime, not when it was instantiated.
  218. """
  219. with self.assertRaises(AttributeError):
  220. getattr(settings, 'TEST')
  221. with self.assertRaises(AttributeError):
  222. getattr(settings, 'TEST2')
  223. inner = override_settings(TEST2='override')
  224. with override_settings(TEST='override'):
  225. self.assertEqual('override', settings.TEST)
  226. with inner:
  227. self.assertEqual('override', settings.TEST)
  228. self.assertEqual('override', settings.TEST2)
  229. # inner's __exit__ should have restored the settings of the outer
  230. # context manager, not those when the class was instantiated
  231. self.assertEqual('override', settings.TEST)
  232. with self.assertRaises(AttributeError):
  233. getattr(settings, 'TEST2')
  234. with self.assertRaises(AttributeError):
  235. getattr(settings, 'TEST')
  236. with self.assertRaises(AttributeError):
  237. getattr(settings, 'TEST2')
  238. def test_no_secret_key(self):
  239. settings_module = ModuleType('fake_settings_module')
  240. sys.modules['fake_settings_module'] = settings_module
  241. msg = 'The SECRET_KEY setting must be set.'
  242. try:
  243. settings = Settings('fake_settings_module')
  244. with self.assertRaisesMessage(ImproperlyConfigured, msg):
  245. settings.SECRET_KEY
  246. finally:
  247. del sys.modules['fake_settings_module']
  248. def test_secret_key_empty_string(self):
  249. settings_module = ModuleType('fake_settings_module')
  250. settings_module.SECRET_KEY = ''
  251. sys.modules['fake_settings_module'] = settings_module
  252. try:
  253. msg = 'The SECRET_KEY setting must not be empty.'
  254. with self.assertRaisesMessage(ImproperlyConfigured, msg):
  255. Settings('fake_settings_module')
  256. finally:
  257. del sys.modules['fake_settings_module']
  258. def test_no_settings_module(self):
  259. msg = (
  260. 'Requested setting%s, but settings are not configured. You '
  261. 'must either define the environment variable DJANGO_SETTINGS_MODULE '
  262. 'or call settings.configure() before accessing settings.'
  263. )
  264. orig_settings = os.environ[ENVIRONMENT_VARIABLE]
  265. os.environ[ENVIRONMENT_VARIABLE] = ''
  266. try:
  267. with self.assertRaisesMessage(ImproperlyConfigured, msg % 's'):
  268. settings._setup()
  269. with self.assertRaisesMessage(ImproperlyConfigured, msg % ' TEST'):
  270. settings._setup('TEST')
  271. finally:
  272. os.environ[ENVIRONMENT_VARIABLE] = orig_settings
  273. def test_already_configured(self):
  274. with self.assertRaisesMessage(RuntimeError, 'Settings already configured.'):
  275. settings.configure()
  276. @requires_tz_support
  277. @mock.patch('django.conf.global_settings.TIME_ZONE', 'test')
  278. def test_incorrect_timezone(self):
  279. with self.assertRaisesMessage(ValueError, 'Incorrect timezone setting: test'):
  280. settings._setup()
  281. class TestComplexSettingOverride(SimpleTestCase):
  282. def setUp(self):
  283. self.old_warn_override_settings = signals.COMPLEX_OVERRIDE_SETTINGS.copy()
  284. signals.COMPLEX_OVERRIDE_SETTINGS.add('TEST_WARN')
  285. def tearDown(self):
  286. signals.COMPLEX_OVERRIDE_SETTINGS = self.old_warn_override_settings
  287. self.assertNotIn('TEST_WARN', signals.COMPLEX_OVERRIDE_SETTINGS)
  288. def test_complex_override_warning(self):
  289. """Regression test for #19031"""
  290. msg = 'Overriding setting TEST_WARN can lead to unexpected behavior.'
  291. with self.assertWarnsMessage(UserWarning, msg) as cm:
  292. with override_settings(TEST_WARN='override'):
  293. self.assertEqual(settings.TEST_WARN, 'override')
  294. self.assertEqual(cm.filename, __file__)
  295. class SecureProxySslHeaderTest(SimpleTestCase):
  296. @override_settings(SECURE_PROXY_SSL_HEADER=None)
  297. def test_none(self):
  298. req = HttpRequest()
  299. self.assertIs(req.is_secure(), False)
  300. @override_settings(SECURE_PROXY_SSL_HEADER=('HTTP_X_FORWARDED_PROTOCOL', 'https'))
  301. def test_set_without_xheader(self):
  302. req = HttpRequest()
  303. self.assertIs(req.is_secure(), False)
  304. @override_settings(SECURE_PROXY_SSL_HEADER=('HTTP_X_FORWARDED_PROTOCOL', 'https'))
  305. def test_set_with_xheader_wrong(self):
  306. req = HttpRequest()
  307. req.META['HTTP_X_FORWARDED_PROTOCOL'] = 'wrongvalue'
  308. self.assertIs(req.is_secure(), False)
  309. @override_settings(SECURE_PROXY_SSL_HEADER=('HTTP_X_FORWARDED_PROTOCOL', 'https'))
  310. def test_set_with_xheader_right(self):
  311. req = HttpRequest()
  312. req.META['HTTP_X_FORWARDED_PROTOCOL'] = 'https'
  313. self.assertIs(req.is_secure(), True)
  314. class IsOverriddenTest(SimpleTestCase):
  315. def test_configure(self):
  316. s = LazySettings()
  317. s.configure(SECRET_KEY='foo')
  318. self.assertTrue(s.is_overridden('SECRET_KEY'))
  319. def test_module(self):
  320. settings_module = ModuleType('fake_settings_module')
  321. settings_module.SECRET_KEY = 'foo'
  322. sys.modules['fake_settings_module'] = settings_module
  323. try:
  324. s = Settings('fake_settings_module')
  325. self.assertTrue(s.is_overridden('SECRET_KEY'))
  326. self.assertFalse(s.is_overridden('ALLOWED_HOSTS'))
  327. finally:
  328. del sys.modules['fake_settings_module']
  329. def test_override(self):
  330. self.assertFalse(settings.is_overridden('ALLOWED_HOSTS'))
  331. with override_settings(ALLOWED_HOSTS=[]):
  332. self.assertTrue(settings.is_overridden('ALLOWED_HOSTS'))
  333. def test_unevaluated_lazysettings_repr(self):
  334. lazy_settings = LazySettings()
  335. expected = '<LazySettings [Unevaluated]>'
  336. self.assertEqual(repr(lazy_settings), expected)
  337. def test_evaluated_lazysettings_repr(self):
  338. lazy_settings = LazySettings()
  339. module = os.environ.get(ENVIRONMENT_VARIABLE)
  340. expected = '<LazySettings "%s">' % module
  341. # Force evaluation of the lazy object.
  342. lazy_settings.APPEND_SLASH
  343. self.assertEqual(repr(lazy_settings), expected)
  344. def test_usersettingsholder_repr(self):
  345. lazy_settings = LazySettings()
  346. lazy_settings.configure(APPEND_SLASH=False)
  347. expected = '<UserSettingsHolder>'
  348. self.assertEqual(repr(lazy_settings._wrapped), expected)
  349. def test_settings_repr(self):
  350. module = os.environ.get(ENVIRONMENT_VARIABLE)
  351. lazy_settings = Settings(module)
  352. expected = '<Settings "%s">' % module
  353. self.assertEqual(repr(lazy_settings), expected)
  354. class TestListSettings(unittest.TestCase):
  355. """
  356. Make sure settings that should be lists or tuples throw
  357. ImproperlyConfigured if they are set to a string instead of a list or tuple.
  358. """
  359. list_or_tuple_settings = (
  360. "INSTALLED_APPS",
  361. "TEMPLATE_DIRS",
  362. "LOCALE_PATHS",
  363. )
  364. def test_tuple_settings(self):
  365. settings_module = ModuleType('fake_settings_module')
  366. settings_module.SECRET_KEY = 'foo'
  367. for setting in self.list_or_tuple_settings:
  368. setattr(settings_module, setting, ('non_list_or_tuple_value'))
  369. sys.modules['fake_settings_module'] = settings_module
  370. try:
  371. with self.assertRaises(ImproperlyConfigured):
  372. Settings('fake_settings_module')
  373. finally:
  374. del sys.modules['fake_settings_module']
  375. delattr(settings_module, setting)