1. import unittest
    
  2. from io import StringIO
    
  3. from unittest import mock
    
  4. 
    
  5. from django.db import DatabaseError, connection
    
  6. from django.db.backends.oracle.creation import DatabaseCreation
    
  7. from django.test import TestCase
    
  8. 
    
  9. 
    
  10. @unittest.skipUnless(connection.vendor == "oracle", "Oracle tests")
    
  11. @mock.patch.object(DatabaseCreation, "_maindb_connection", return_value=connection)
    
  12. @mock.patch("sys.stdout", new_callable=StringIO)
    
  13. @mock.patch("sys.stderr", new_callable=StringIO)
    
  14. class DatabaseCreationTests(TestCase):
    
  15.     def _execute_raise_user_already_exists(
    
  16.         self, cursor, statements, parameters, verbosity, allow_quiet_fail=False
    
  17.     ):
    
  18.         # Raise "user already exists" only in test user creation
    
  19.         if statements and statements[0].startswith("CREATE USER"):
    
  20.             raise DatabaseError(
    
  21.                 "ORA-01920: user name 'string' conflicts with another user or role name"
    
  22.             )
    
  23. 
    
  24.     def _execute_raise_tablespace_already_exists(
    
  25.         self, cursor, statements, parameters, verbosity, allow_quiet_fail=False
    
  26.     ):
    
  27.         raise DatabaseError("ORA-01543: tablespace 'string' already exists")
    
  28. 
    
  29.     def _execute_raise_insufficient_privileges(
    
  30.         self, cursor, statements, parameters, verbosity, allow_quiet_fail=False
    
  31.     ):
    
  32.         raise DatabaseError("ORA-01031: insufficient privileges")
    
  33. 
    
  34.     def _test_database_passwd(self):
    
  35.         # Mocked to avoid test user password changed
    
  36.         return connection.settings_dict["SAVED_PASSWORD"]
    
  37. 
    
  38.     def patch_execute_statements(self, execute_statements):
    
  39.         return mock.patch.object(
    
  40.             DatabaseCreation, "_execute_statements", execute_statements
    
  41.         )
    
  42. 
    
  43.     @mock.patch.object(DatabaseCreation, "_test_user_create", return_value=False)
    
  44.     def test_create_test_db(self, *mocked_objects):
    
  45.         creation = DatabaseCreation(connection)
    
  46.         # Simulate test database creation raising "tablespace already exists"
    
  47.         with self.patch_execute_statements(
    
  48.             self._execute_raise_tablespace_already_exists
    
  49.         ):
    
  50.             with mock.patch("builtins.input", return_value="no"):
    
  51.                 with self.assertRaises(SystemExit):
    
  52.                     # SystemExit is raised if the user answers "no" to the
    
  53.                     # prompt asking if it's okay to delete the test tablespace.
    
  54.                     creation._create_test_db(verbosity=0, keepdb=False)
    
  55.             # "Tablespace already exists" error is ignored when keepdb is on
    
  56.             creation._create_test_db(verbosity=0, keepdb=True)
    
  57.         # Simulate test database creation raising unexpected error
    
  58.         with self.patch_execute_statements(self._execute_raise_insufficient_privileges):
    
  59.             with self.assertRaises(SystemExit):
    
  60.                 creation._create_test_db(verbosity=0, keepdb=False)
    
  61.             with self.assertRaises(SystemExit):
    
  62.                 creation._create_test_db(verbosity=0, keepdb=True)
    
  63. 
    
  64.     @mock.patch.object(DatabaseCreation, "_test_database_create", return_value=False)
    
  65.     def test_create_test_user(self, *mocked_objects):
    
  66.         creation = DatabaseCreation(connection)
    
  67.         with mock.patch.object(
    
  68.             DatabaseCreation, "_test_database_passwd", self._test_database_passwd
    
  69.         ):
    
  70.             # Simulate test user creation raising "user already exists"
    
  71.             with self.patch_execute_statements(self._execute_raise_user_already_exists):
    
  72.                 with mock.patch("builtins.input", return_value="no"):
    
  73.                     with self.assertRaises(SystemExit):
    
  74.                         # SystemExit is raised if the user answers "no" to the
    
  75.                         # prompt asking if it's okay to delete the test user.
    
  76.                         creation._create_test_db(verbosity=0, keepdb=False)
    
  77.                 # "User already exists" error is ignored when keepdb is on
    
  78.                 creation._create_test_db(verbosity=0, keepdb=True)
    
  79.             # Simulate test user creation raising unexpected error
    
  80.             with self.patch_execute_statements(
    
  81.                 self._execute_raise_insufficient_privileges
    
  82.             ):
    
  83.                 with self.assertRaises(SystemExit):
    
  84.                     creation._create_test_db(verbosity=0, keepdb=False)
    
  85.                 with self.assertRaises(SystemExit):
    
  86.                     creation._create_test_db(verbosity=0, keepdb=True)
    
  87. 
    
  88.     def test_oracle_managed_files(self, *mocked_objects):
    
  89.         def _execute_capture_statements(
    
  90.             self, cursor, statements, parameters, verbosity, allow_quiet_fail=False
    
  91.         ):
    
  92.             self.tblspace_sqls = statements
    
  93. 
    
  94.         creation = DatabaseCreation(connection)
    
  95.         # Simulate test database creation with Oracle Managed File (OMF)
    
  96.         # tablespaces.
    
  97.         with mock.patch.object(
    
  98.             DatabaseCreation, "_test_database_oracle_managed_files", return_value=True
    
  99.         ):
    
  100.             with self.patch_execute_statements(_execute_capture_statements):
    
  101.                 with connection.cursor() as cursor:
    
  102.                     creation._execute_test_db_creation(
    
  103.                         cursor, creation._get_test_db_params(), verbosity=0
    
  104.                     )
    
  105.                     tblspace_sql, tblspace_tmp_sql = creation.tblspace_sqls
    
  106.                     # Datafile names shouldn't appear.
    
  107.                     self.assertIn("DATAFILE SIZE", tblspace_sql)
    
  108.                     self.assertIn("TEMPFILE SIZE", tblspace_tmp_sql)
    
  109.                     # REUSE cannot be used with OMF.
    
  110.                     self.assertNotIn("REUSE", tblspace_sql)
    
  111.                     self.assertNotIn("REUSE", tblspace_tmp_sql)