Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse code

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
  • Loading branch information...
commit 03a442c8ad6addf8c223ca0d3864a9d58d409d44 1 parent 530ab32
Claude Paroz authored April 24, 2012
66  django/test/simple.py
@@ -193,31 +193,35 @@ def reorder_suite(suite, classes):
193 193
 
194 194
 
195 195
 def dependency_ordered(test_databases, dependencies):
196  
-    """Reorder test_databases into an order that honors the dependencies
  196
+    """
  197
+    Reorder test_databases into an order that honors the dependencies
197 198
     described in TEST_DEPENDENCIES.
198 199
     """
199 200
     ordered_test_databases = []
200 201
     resolved_databases = set()
  202
+
  203
+    # Maps db signature to dependencies of all it's aliases
  204
+    dependencies_map = {}
  205
+
  206
+    # sanity check - no DB can depend on it's own alias
  207
+    for sig, (_, aliases) in test_databases:
  208
+        all_deps = set()
  209
+        for alias in aliases:
  210
+            all_deps.update(dependencies.get(alias, []))
  211
+        if not all_deps.isdisjoint(aliases):
  212
+            raise ImproperlyConfigured(
  213
+                "Circular dependency: databases %r depend on each other, "
  214
+                "but are aliases." % aliases)
  215
+        dependencies_map[sig] = all_deps
  216
+
201 217
     while test_databases:
202 218
         changed = False
203 219
         deferred = []
204 220
 
205  
-        while test_databases:
206  
-            signature, (db_name, aliases) = test_databases.pop()
207  
-            dependencies_satisfied = True
208  
-            for alias in aliases:
209  
-                if alias in dependencies:
210  
-                    if all(a in resolved_databases
211  
-                           for a in dependencies[alias]):
212  
-                        # all dependencies for this alias are satisfied
213  
-                        dependencies.pop(alias)
214  
-                        resolved_databases.add(alias)
215  
-                    else:
216  
-                        dependencies_satisfied = False
217  
-                else:
218  
-                    resolved_databases.add(alias)
219  
-
220  
-            if dependencies_satisfied:
  221
+        # Try to find a DB that has all it's dependencies met
  222
+        for signature, (db_name, aliases) in test_databases:
  223
+            if dependencies_map[signature].issubset(resolved_databases):
  224
+                resolved_databases.update(aliases)
221 225
                 ordered_test_databases.append((signature, (db_name, aliases)))
222 226
                 changed = True
223 227
             else:
@@ -282,9 +286,9 @@ def setup_databases(self, **kwargs):
282 286
                 # we only need to create the test database once.
283 287
                 item = test_databases.setdefault(
284 288
                     connection.creation.test_db_signature(),
285  
-                    (connection.settings_dict['NAME'], [])
  289
+                    (connection.settings_dict['NAME'], set())
286 290
                 )
287  
-                item[1].append(alias)
  291
+                item[1].add(alias)
288 292
 
289 293
                 if 'TEST_DEPENDENCIES' in connection.settings_dict:
290 294
                     dependencies[alias] = (
@@ -297,26 +301,20 @@ def setup_databases(self, **kwargs):
297 301
         # Second pass -- actually create the databases.
298 302
         old_names = []
299 303
         mirrors = []
  304
+
300 305
         for signature, (db_name, aliases) in dependency_ordered(
301 306
             test_databases.items(), dependencies):
  307
+            test_db_name = None
302 308
             # Actually create the database for the first connection
303  
-            connection = connections[aliases[0]]
304  
-            old_names.append((connection, db_name, True))
305  
-            test_db_name = connection.creation.create_test_db(
306  
-                self.verbosity, autoclobber=not self.interactive)
307  
-            for alias in aliases[1:]:
  309
+
  310
+            for alias in aliases:
308 311
                 connection = connections[alias]
309  
-                if db_name:
310  
-                    old_names.append((connection, db_name, False))
311  
-                    connection.settings_dict['NAME'] = test_db_name
  312
+                old_names.append((connection, db_name, True))
  313
+                if test_db_name is None:
  314
+                    test_db_name = connection.creation.create_test_db(
  315
+                            self.verbosity, autoclobber=not self.interactive)
312 316
                 else:
313  
-                    # If settings_dict['NAME'] isn't defined, we have a backend
314  
-                    # where the name isn't important -- e.g., SQLite, which
315  
-                    # uses :memory:. Force create the database instead of
316  
-                    # assuming it's a duplicate.
317  
-                    old_names.append((connection, db_name, True))
318  
-                    connection.creation.create_test_db(
319  
-                        self.verbosity, autoclobber=not self.interactive)
  317
+                    connection.settings_dict['NAME'] = test_db_name
320 318
 
321 319
         for alias, mirror_alias in mirrored_aliases.items():
322 320
             mirrors.append((alias, connections[alias].settings_dict['NAME']))
19  tests/regressiontests/test_runner/tests.py
@@ -110,6 +110,25 @@ def test_circular_dependencies(self):
110 110
 
111 111
         self.assertRaises(ImproperlyConfigured, simple.dependency_ordered, raw, dependencies=dependencies)
112 112
 
  113
+    def test_own_alias_dependency(self):
  114
+        raw = [
  115
+            ('s1', ('s1_db', ['alpha', 'bravo']))
  116
+        ]
  117
+        dependencies = {
  118
+            'alpha': ['bravo']
  119
+        }
  120
+
  121
+        with self.assertRaises(ImproperlyConfigured):
  122
+            simple.dependency_ordered(raw, dependencies=dependencies)
  123
+
  124
+        # reordering aliases shouldn't matter
  125
+        raw = [
  126
+            ('s1', ('s1_db', ['bravo', 'alpha']))
  127
+        ]
  128
+
  129
+        with self.assertRaises(ImproperlyConfigured):
  130
+            simple.dependency_ordered(raw, dependencies=dependencies)
  131
+
113 132
 
114 133
 class MockTestRunner(object):
115 134
     invoked = False

0 notes on commit 03a442c

Please sign in to comment.
Something went wrong with that request. Please try again.