Fixed #17954 -- Fixed dependency checking for test databases. Thanks Łukasz Rekucki for the report and the patch.
git-svn-id: http://code.djangoproject.com/svn/django/trunk@17931 bcc190cf-cafb-0310-a4f2-bffc1f526a37
This commit is contained in:
parent
530ab32e9f
commit
03a442c8ad
|
@ -193,31 +193,35 @@ def reorder_suite(suite, classes):
|
|||
|
||||
|
||||
def dependency_ordered(test_databases, dependencies):
|
||||
"""Reorder test_databases into an order that honors the dependencies
|
||||
"""
|
||||
Reorder test_databases into an order that honors the dependencies
|
||||
described in TEST_DEPENDENCIES.
|
||||
"""
|
||||
ordered_test_databases = []
|
||||
resolved_databases = set()
|
||||
|
||||
# Maps db signature to dependencies of all it's aliases
|
||||
dependencies_map = {}
|
||||
|
||||
# sanity check - no DB can depend on it's own alias
|
||||
for sig, (_, aliases) in test_databases:
|
||||
all_deps = set()
|
||||
for alias in aliases:
|
||||
all_deps.update(dependencies.get(alias, []))
|
||||
if not all_deps.isdisjoint(aliases):
|
||||
raise ImproperlyConfigured(
|
||||
"Circular dependency: databases %r depend on each other, "
|
||||
"but are aliases." % aliases)
|
||||
dependencies_map[sig] = all_deps
|
||||
|
||||
while test_databases:
|
||||
changed = False
|
||||
deferred = []
|
||||
|
||||
while test_databases:
|
||||
signature, (db_name, aliases) = test_databases.pop()
|
||||
dependencies_satisfied = True
|
||||
for alias in aliases:
|
||||
if alias in dependencies:
|
||||
if all(a in resolved_databases
|
||||
for a in dependencies[alias]):
|
||||
# all dependencies for this alias are satisfied
|
||||
dependencies.pop(alias)
|
||||
resolved_databases.add(alias)
|
||||
else:
|
||||
dependencies_satisfied = False
|
||||
else:
|
||||
resolved_databases.add(alias)
|
||||
|
||||
if dependencies_satisfied:
|
||||
# Try to find a DB that has all it's dependencies met
|
||||
for signature, (db_name, aliases) in test_databases:
|
||||
if dependencies_map[signature].issubset(resolved_databases):
|
||||
resolved_databases.update(aliases)
|
||||
ordered_test_databases.append((signature, (db_name, aliases)))
|
||||
changed = True
|
||||
else:
|
||||
|
@ -282,9 +286,9 @@ class DjangoTestSuiteRunner(object):
|
|||
# we only need to create the test database once.
|
||||
item = test_databases.setdefault(
|
||||
connection.creation.test_db_signature(),
|
||||
(connection.settings_dict['NAME'], [])
|
||||
(connection.settings_dict['NAME'], set())
|
||||
)
|
||||
item[1].append(alias)
|
||||
item[1].add(alias)
|
||||
|
||||
if 'TEST_DEPENDENCIES' in connection.settings_dict:
|
||||
dependencies[alias] = (
|
||||
|
@ -297,26 +301,20 @@ class DjangoTestSuiteRunner(object):
|
|||
# Second pass -- actually create the databases.
|
||||
old_names = []
|
||||
mirrors = []
|
||||
|
||||
for signature, (db_name, aliases) in dependency_ordered(
|
||||
test_databases.items(), dependencies):
|
||||
test_db_name = None
|
||||
# Actually create the database for the first connection
|
||||
connection = connections[aliases[0]]
|
||||
old_names.append((connection, db_name, True))
|
||||
test_db_name = connection.creation.create_test_db(
|
||||
self.verbosity, autoclobber=not self.interactive)
|
||||
for alias in aliases[1:]:
|
||||
|
||||
for alias in aliases:
|
||||
connection = connections[alias]
|
||||
if db_name:
|
||||
old_names.append((connection, db_name, False))
|
||||
connection.settings_dict['NAME'] = test_db_name
|
||||
old_names.append((connection, db_name, True))
|
||||
if test_db_name is None:
|
||||
test_db_name = connection.creation.create_test_db(
|
||||
self.verbosity, autoclobber=not self.interactive)
|
||||
else:
|
||||
# If settings_dict['NAME'] isn't defined, we have a backend
|
||||
# where the name isn't important -- e.g., SQLite, which
|
||||
# uses :memory:. Force create the database instead of
|
||||
# assuming it's a duplicate.
|
||||
old_names.append((connection, db_name, True))
|
||||
connection.creation.create_test_db(
|
||||
self.verbosity, autoclobber=not self.interactive)
|
||||
connection.settings_dict['NAME'] = test_db_name
|
||||
|
||||
for alias, mirror_alias in mirrored_aliases.items():
|
||||
mirrors.append((alias, connections[alias].settings_dict['NAME']))
|
||||
|
|
|
@ -110,6 +110,25 @@ class DependencyOrderingTests(unittest.TestCase):
|
|||
|
||||
self.assertRaises(ImproperlyConfigured, simple.dependency_ordered, raw, dependencies=dependencies)
|
||||
|
||||
def test_own_alias_dependency(self):
|
||||
raw = [
|
||||
('s1', ('s1_db', ['alpha', 'bravo']))
|
||||
]
|
||||
dependencies = {
|
||||
'alpha': ['bravo']
|
||||
}
|
||||
|
||||
with self.assertRaises(ImproperlyConfigured):
|
||||
simple.dependency_ordered(raw, dependencies=dependencies)
|
||||
|
||||
# reordering aliases shouldn't matter
|
||||
raw = [
|
||||
('s1', ('s1_db', ['bravo', 'alpha']))
|
||||
]
|
||||
|
||||
with self.assertRaises(ImproperlyConfigured):
|
||||
simple.dependency_ordered(raw, dependencies=dependencies)
|
||||
|
||||
|
||||
class MockTestRunner(object):
|
||||
invoked = False
|
||||
|
|
Loading…
Reference in New Issue