1
0
mirror of https://github.com/django/django.git synced 2025-11-07 07:15:35 +00:00

[1.7.x] Fixed bug in circular dependency algo for migration dependencies.

Previous algo only worked if the first item was a part of the loop,
and you would get an infinite loop otherwise (see test).

To fix this, it was much easier to do a pre-pass.

A bonus is that you now get an error message that actually helps you debug
the dependency problem.

Backport of ff3d746e8d from master, with
additional tests from c5def493d0
This commit is contained in:
Luke Plant
2014-11-26 08:03:10 +00:00
parent 2a20bccda9
commit 8e3c3be32d
2 changed files with 71 additions and 16 deletions

View File

@@ -134,6 +134,20 @@ class GraphTests(TestCase):
graph.forwards_plan, ("app_a", "0003"),
)
def test_circular_graph_2(self):
graph = MigrationGraph()
graph.add_node(('A', '0001'), None)
graph.add_node(('C', '0001'), None)
graph.add_node(('B', '0001'), None)
graph.add_dependency('A.0001', ('A', '0001'),('B', '0001'))
graph.add_dependency('B.0001', ('B', '0001'),('A', '0001'))
graph.add_dependency('C.0001', ('C', '0001'),('B', '0001'))
self.assertRaises(
CircularDependencyError,
graph.forwards_plan, ('C', '0001')
)
def test_dfs(self):
graph = MigrationGraph()
root = ("app_a", "1")
@@ -188,3 +202,30 @@ class GraphTests(TestCase):
msg = "Migration app_a.0002 dependencies reference nonexistent child node ('app_a', '0002')"
with self.assertRaisesMessage(KeyError, msg):
graph.add_dependency("app_a.0002", ("app_a", "0002"), ("app_a", "0001"))
def test_infinite_loop(self):
"""
Tests a complex dependency graph:
app_a: 0001 <-
\
app_b: 0001 <- x 0002 <-
/ \
app_c: 0001<- <------------- x 0002
And apply sqashing on app_c.
"""
graph = MigrationGraph()
graph.add_node(("app_a", "0001"), None)
graph.add_node(("app_b", "0001"), None)
graph.add_node(("app_b", "0002"), None)
graph.add_node(("app_c", "0001_squashed_0002"), None)
graph.add_dependency("app_b.0001", ("app_b", "0001"), ("app_c", "0001_squashed_0002"))
graph.add_dependency("app_b.0002", ("app_b", "0002"), ("app_a", "0001"))
graph.add_dependency("app_b.0002", ("app_b", "0002"), ("app_b", "0001"))
graph.add_dependency("app_c.0001_squashed_0002", ("app_c", "0001_squashed_0002"), ("app_b", "0002"))
with self.assertRaises(CircularDependencyError):
graph.forwards_plan(("app_c", "0001_squashed_0002"))