tests.py 17 KB

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