mirror of
https://github.com/django/django.git
synced 2025-11-18 02:56:45 +00:00
Merge c2822f58fb into 1ce6e78dd4
This commit is contained in:
commit
148308ec7a
2 changed files with 97 additions and 6 deletions
|
|
@ -56,8 +56,28 @@ class DatabaseCreation(BaseDatabaseCreation):
|
|||
source_database_name = orig_settings_dict["NAME"] or ":memory:"
|
||||
|
||||
if not self.is_in_memory_db(source_database_name):
|
||||
root, ext = os.path.splitext(source_database_name)
|
||||
return {**orig_settings_dict, "NAME": f"{root}_{suffix}{ext}"}
|
||||
if source_database_name.startswith("file:"):
|
||||
if "?" in source_database_name:
|
||||
base, query = source_database_name.split("?", 1)
|
||||
return {
|
||||
**orig_settings_dict,
|
||||
"NAME": f"{base}_{suffix}?{query}",
|
||||
}
|
||||
else:
|
||||
return {
|
||||
**orig_settings_dict,
|
||||
"NAME": f"{source_database_name}_{suffix}",
|
||||
}
|
||||
else:
|
||||
root, ext = os.path.splitext(source_database_name)
|
||||
clone_name = f"{root}_{suffix}{ext}"
|
||||
clone_dir = os.path.dirname(clone_name)
|
||||
if clone_dir:
|
||||
os.makedirs(clone_dir, exist_ok=True)
|
||||
return {
|
||||
**orig_settings_dict,
|
||||
"NAME": clone_name,
|
||||
}
|
||||
|
||||
start_method = multiprocessing.get_start_method()
|
||||
if start_method == "fork":
|
||||
|
|
@ -93,6 +113,10 @@ class DatabaseCreation(BaseDatabaseCreation):
|
|||
except Exception as e:
|
||||
self.log("Got an error deleting the old test database: %s" % e)
|
||||
sys.exit(2)
|
||||
target_dir = os.path.dirname(str(target_database_name))
|
||||
if target_dir:
|
||||
os.makedirs(target_dir, exist_ok=True)
|
||||
|
||||
try:
|
||||
shutil.copy(source_database_name, target_database_name)
|
||||
except Exception as e:
|
||||
|
|
@ -102,7 +126,15 @@ class DatabaseCreation(BaseDatabaseCreation):
|
|||
# Forkserver and spawn require migrating to disk which will be
|
||||
# re-opened in setup_worker_connection.
|
||||
elif multiprocessing.get_start_method() in {"forkserver", "spawn"}:
|
||||
ondisk_db = sqlite3.connect(target_database_name, uri=True)
|
||||
target_dir = os.path.dirname(str(target_database_name))
|
||||
if target_dir:
|
||||
os.makedirs(target_dir, exist_ok=True)
|
||||
# Open on-disk database using a proper URI.
|
||||
if str(target_database_name).startswith("file:"):
|
||||
ondisk_uri = str(target_database_name)
|
||||
else:
|
||||
ondisk_uri = f"file:{target_database_name}"
|
||||
ondisk_db = sqlite3.connect(ondisk_uri, uri=True)
|
||||
self.connection.connection.backup(ondisk_db)
|
||||
ondisk_db.close()
|
||||
|
||||
|
|
@ -142,9 +174,17 @@ class DatabaseCreation(BaseDatabaseCreation):
|
|||
connection_str = (
|
||||
f"file:memorydb_{alias}_{_worker_id}?mode=memory&cache=shared"
|
||||
)
|
||||
source_db = self.connection.Database.connect(
|
||||
f"file:{alias}_{_worker_id}.sqlite3?mode=ro", uri=True
|
||||
)
|
||||
source_name = str(settings_dict["NAME"])
|
||||
if source_name.startswith("file:"):
|
||||
# Ensure read-only mode is set on URI.
|
||||
source_uri = (
|
||||
f"{source_name}&mode=ro"
|
||||
if "?" in source_name
|
||||
else f"{source_name}?mode=ro"
|
||||
)
|
||||
else:
|
||||
source_uri = f"file:{source_name}?mode=ro"
|
||||
source_db = self.connection.Database.connect(source_uri, uri=True)
|
||||
target_db = sqlite3.connect(connection_str, uri=True)
|
||||
source_db.backup(target_db)
|
||||
source_db.close()
|
||||
|
|
|
|||
51
tests/backends/sqlite/test_parallel.py
Normal file
51
tests/backends/sqlite/test_parallel.py
Normal file
|
|
@ -0,0 +1,51 @@
|
|||
import shutil
|
||||
import tempfile
|
||||
import unittest
|
||||
from pathlib import Path
|
||||
|
||||
from django.db import connection, connections
|
||||
from django.test import TestCase
|
||||
|
||||
|
||||
@unittest.skipUnless(connection.vendor == "sqlite", "SQLite tests")
|
||||
class SQLiteParallelCloneTests(TestCase):
|
||||
"""
|
||||
Tests that cloned SQLite test databases respect the original
|
||||
directory when running tests in parallel.
|
||||
"""
|
||||
|
||||
def setUp(self):
|
||||
self.test_db_dir = Path(tempfile.mkdtemp()) / "db" / "default"
|
||||
self.test_db_dir.mkdir(parents=True, exist_ok=True)
|
||||
|
||||
self.original_settings = None
|
||||
|
||||
self.addCleanup(
|
||||
lambda: shutil.rmtree(self.test_db_dir.parent.parent, ignore_errors=True)
|
||||
)
|
||||
|
||||
def tearDown(self):
|
||||
if self.original_settings is not None:
|
||||
conn = connections["default"]
|
||||
conn.settings_dict["NAME"] = self.original_settings["NAME"]
|
||||
conn.settings_dict["TEST"]["NAME"] = self.original_settings["TEST"]["NAME"]
|
||||
|
||||
def test_clone_respects_directory(self):
|
||||
conn = connections["default"]
|
||||
self.original_settings = {
|
||||
"NAME": conn.settings_dict["NAME"],
|
||||
"TEST": {"NAME": conn.settings_dict["TEST"]["NAME"]},
|
||||
}
|
||||
|
||||
conn.close()
|
||||
|
||||
db_path = str(self.test_db_dir / "db.sqlite3")
|
||||
conn.settings_dict["NAME"] = db_path
|
||||
conn.settings_dict["TEST"]["NAME"] = str(self.test_db_dir / "test_db.sqlite3")
|
||||
|
||||
clone = conn.creation.get_test_db_clone_settings(1)
|
||||
|
||||
clone_path = Path(clone["NAME"])
|
||||
self.assertIn("db", clone_path.parts)
|
||||
self.assertIn("default", clone_path.parts)
|
||||
self.assertTrue(clone_path.name.startswith("db_1"))
|
||||
Loading…
Add table
Add a link
Reference in a new issue