test_creation.py 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102
  1. import unittest
  2. from contextlib import contextmanager
  3. from io import StringIO
  4. from unittest import mock
  5. from django.db import DatabaseError, connection
  6. from django.db.backends.base.creation import BaseDatabaseCreation
  7. from django.test import SimpleTestCase
  8. try:
  9. import psycopg2 # NOQA
  10. except ImportError:
  11. pass
  12. else:
  13. from psycopg2 import errorcodes
  14. from django.db.backends.postgresql.creation import DatabaseCreation
  15. @unittest.skipUnless(connection.vendor == 'postgresql', 'PostgreSQL tests')
  16. class DatabaseCreationTests(SimpleTestCase):
  17. @contextmanager
  18. def changed_test_settings(self, **kwargs):
  19. settings = connection.settings_dict['TEST']
  20. saved_values = {}
  21. for name in kwargs:
  22. if name in settings:
  23. saved_values[name] = settings[name]
  24. for name, value in kwargs.items():
  25. settings[name] = value
  26. try:
  27. yield
  28. finally:
  29. for name in kwargs:
  30. if name in saved_values:
  31. settings[name] = saved_values[name]
  32. else:
  33. del settings[name]
  34. def check_sql_table_creation_suffix(self, settings, expected):
  35. with self.changed_test_settings(**settings):
  36. creation = DatabaseCreation(connection)
  37. suffix = creation.sql_table_creation_suffix()
  38. self.assertEqual(suffix, expected)
  39. def test_sql_table_creation_suffix_with_none_settings(self):
  40. settings = {'CHARSET': None, 'TEMPLATE': None}
  41. self.check_sql_table_creation_suffix(settings, "")
  42. def test_sql_table_creation_suffix_with_encoding(self):
  43. settings = {'CHARSET': 'UTF8'}
  44. self.check_sql_table_creation_suffix(settings, "WITH ENCODING 'UTF8'")
  45. def test_sql_table_creation_suffix_with_template(self):
  46. settings = {'TEMPLATE': 'template0'}
  47. self.check_sql_table_creation_suffix(settings, 'WITH TEMPLATE "template0"')
  48. def test_sql_table_creation_suffix_with_encoding_and_template(self):
  49. settings = {'CHARSET': 'UTF8', 'TEMPLATE': 'template0'}
  50. self.check_sql_table_creation_suffix(settings, '''WITH ENCODING 'UTF8' TEMPLATE "template0"''')
  51. def _execute_raise_database_already_exists(self, cursor, parameters, keepdb=False):
  52. error = DatabaseError('database %s already exists' % parameters['dbname'])
  53. error.pgcode = errorcodes.DUPLICATE_DATABASE
  54. raise DatabaseError() from error
  55. def _execute_raise_permission_denied(self, cursor, parameters, keepdb=False):
  56. error = DatabaseError('permission denied to create database')
  57. error.pgcode = errorcodes.INSUFFICIENT_PRIVILEGE
  58. raise DatabaseError() from error
  59. def patch_test_db_creation(self, execute_create_test_db):
  60. return mock.patch.object(BaseDatabaseCreation, '_execute_create_test_db', execute_create_test_db)
  61. @mock.patch('sys.stdout', new_callable=StringIO)
  62. @mock.patch('sys.stderr', new_callable=StringIO)
  63. def test_create_test_db(self, *mocked_objects):
  64. creation = DatabaseCreation(connection)
  65. # Simulate test database creation raising "database already exists"
  66. with self.patch_test_db_creation(self._execute_raise_database_already_exists):
  67. with mock.patch('builtins.input', return_value='no'):
  68. with self.assertRaises(SystemExit):
  69. # SystemExit is raised if the user answers "no" to the
  70. # prompt asking if it's okay to delete the test database.
  71. creation._create_test_db(verbosity=0, autoclobber=False, keepdb=False)
  72. # "Database already exists" error is ignored when keepdb is on
  73. creation._create_test_db(verbosity=0, autoclobber=False, keepdb=True)
  74. # Simulate test database creation raising unexpected error
  75. with self.patch_test_db_creation(self._execute_raise_permission_denied):
  76. with mock.patch.object(DatabaseCreation, '_database_exists', return_value=False):
  77. with self.assertRaises(SystemExit):
  78. creation._create_test_db(verbosity=0, autoclobber=False, keepdb=False)
  79. with self.assertRaises(SystemExit):
  80. creation._create_test_db(verbosity=0, autoclobber=False, keepdb=True)
  81. # Simulate test database creation raising "insufficient privileges".
  82. # An error shouldn't appear when keepdb is on and the database already
  83. # exists.
  84. with self.patch_test_db_creation(self._execute_raise_permission_denied):
  85. with mock.patch.object(DatabaseCreation, '_database_exists', return_value=True):
  86. creation._create_test_db(verbosity=0, autoclobber=False, keepdb=True)