~ubuntu-branches/debian/sid/python-django/sid

« back to all changes in this revision

Viewing changes to tests/migrations/test_graph.py

  • Committer: Package Import Robot
  • Author(s): Raphaël Hertzog
  • Date: 2014-09-17 14:15:11 UTC
  • mfrom: (1.3.17) (6.2.18 experimental)
  • Revision ID: package-import@ubuntu.com-20140917141511-icneokthe9ww5sk4
Tags: 1.7-2
* Release to unstable.
* Add a migrate-south sample script to help users apply their South
  migrations. Thanks to Brian May.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
from django.test import TestCase
 
2
from django.db.migrations.graph import MigrationGraph, CircularDependencyError
 
3
 
 
4
 
 
5
class GraphTests(TestCase):
 
6
    """
 
7
    Tests the digraph structure.
 
8
    """
 
9
 
 
10
    def test_simple_graph(self):
 
11
        """
 
12
        Tests a basic dependency graph:
 
13
 
 
14
        app_a:  0001 <-- 0002 <--- 0003 <-- 0004
 
15
                                 /
 
16
        app_b:  0001 <-- 0002 <-/
 
17
        """
 
18
        # Build graph
 
19
        graph = MigrationGraph()
 
20
        graph.add_node(("app_a", "0001"), None)
 
21
        graph.add_node(("app_a", "0002"), None)
 
22
        graph.add_node(("app_a", "0003"), None)
 
23
        graph.add_node(("app_a", "0004"), None)
 
24
        graph.add_node(("app_b", "0001"), None)
 
25
        graph.add_node(("app_b", "0002"), None)
 
26
        graph.add_dependency("app_a.0004", ("app_a", "0004"), ("app_a", "0003"))
 
27
        graph.add_dependency("app_a.0003", ("app_a", "0003"), ("app_a", "0002"))
 
28
        graph.add_dependency("app_a.0002", ("app_a", "0002"), ("app_a", "0001"))
 
29
        graph.add_dependency("app_a.0003", ("app_a", "0003"), ("app_b", "0002"))
 
30
        graph.add_dependency("app_b.0002", ("app_b", "0002"), ("app_b", "0001"))
 
31
        # Test root migration case
 
32
        self.assertEqual(
 
33
            graph.forwards_plan(("app_a", "0001")),
 
34
            [('app_a', '0001')],
 
35
        )
 
36
        # Test branch B only
 
37
        self.assertEqual(
 
38
            graph.forwards_plan(("app_b", "0002")),
 
39
            [("app_b", "0001"), ("app_b", "0002")],
 
40
        )
 
41
        # Test whole graph
 
42
        self.assertEqual(
 
43
            graph.forwards_plan(("app_a", "0004")),
 
44
            [('app_b', '0001'), ('app_b', '0002'), ('app_a', '0001'), ('app_a', '0002'), ('app_a', '0003'), ('app_a', '0004')],
 
45
        )
 
46
        # Test reverse to b:0002
 
47
        self.assertEqual(
 
48
            graph.backwards_plan(("app_b", "0002")),
 
49
            [('app_a', '0004'), ('app_a', '0003'), ('app_b', '0002')],
 
50
        )
 
51
        # Test roots and leaves
 
52
        self.assertEqual(
 
53
            graph.root_nodes(),
 
54
            [('app_a', '0001'), ('app_b', '0001')],
 
55
        )
 
56
        self.assertEqual(
 
57
            graph.leaf_nodes(),
 
58
            [('app_a', '0004'), ('app_b', '0002')],
 
59
        )
 
60
 
 
61
    def test_complex_graph(self):
 
62
        """
 
63
        Tests a complex dependency graph:
 
64
 
 
65
        app_a:  0001 <-- 0002 <--- 0003 <-- 0004
 
66
                      \        \ /         /
 
67
        app_b:  0001 <-\ 0002 <-X         /
 
68
                      \          \       /
 
69
        app_c:         \ 0001 <-- 0002 <-
 
70
        """
 
71
        # Build graph
 
72
        graph = MigrationGraph()
 
73
        graph.add_node(("app_a", "0001"), None)
 
74
        graph.add_node(("app_a", "0002"), None)
 
75
        graph.add_node(("app_a", "0003"), None)
 
76
        graph.add_node(("app_a", "0004"), None)
 
77
        graph.add_node(("app_b", "0001"), None)
 
78
        graph.add_node(("app_b", "0002"), None)
 
79
        graph.add_node(("app_c", "0001"), None)
 
80
        graph.add_node(("app_c", "0002"), None)
 
81
        graph.add_dependency("app_a.0004", ("app_a", "0004"), ("app_a", "0003"))
 
82
        graph.add_dependency("app_a.0003", ("app_a", "0003"), ("app_a", "0002"))
 
83
        graph.add_dependency("app_a.0002", ("app_a", "0002"), ("app_a", "0001"))
 
84
        graph.add_dependency("app_a.0003", ("app_a", "0003"), ("app_b", "0002"))
 
85
        graph.add_dependency("app_b.0002", ("app_b", "0002"), ("app_b", "0001"))
 
86
        graph.add_dependency("app_a.0004", ("app_a", "0004"), ("app_c", "0002"))
 
87
        graph.add_dependency("app_c.0002", ("app_c", "0002"), ("app_c", "0001"))
 
88
        graph.add_dependency("app_c.0001", ("app_c", "0001"), ("app_b", "0001"))
 
89
        graph.add_dependency("app_c.0002", ("app_c", "0002"), ("app_a", "0002"))
 
90
        # Test branch C only
 
91
        self.assertEqual(
 
92
            graph.forwards_plan(("app_c", "0002")),
 
93
            [('app_b', '0001'), ('app_c', '0001'), ('app_a', '0001'), ('app_a', '0002'), ('app_c', '0002')],
 
94
        )
 
95
        # Test whole graph
 
96
        self.assertEqual(
 
97
            graph.forwards_plan(("app_a", "0004")),
 
98
            [('app_b', '0001'), ('app_c', '0001'), ('app_a', '0001'), ('app_a', '0002'), ('app_c', '0002'), ('app_b', '0002'), ('app_a', '0003'), ('app_a', '0004')],
 
99
        )
 
100
        # Test reverse to b:0001
 
101
        self.assertEqual(
 
102
            graph.backwards_plan(("app_b", "0001")),
 
103
            [('app_a', '0004'), ('app_c', '0002'), ('app_c', '0001'), ('app_a', '0003'), ('app_b', '0002'), ('app_b', '0001')],
 
104
        )
 
105
        # Test roots and leaves
 
106
        self.assertEqual(
 
107
            graph.root_nodes(),
 
108
            [('app_a', '0001'), ('app_b', '0001'), ('app_c', '0001')],
 
109
        )
 
110
        self.assertEqual(
 
111
            graph.leaf_nodes(),
 
112
            [('app_a', '0004'), ('app_b', '0002'), ('app_c', '0002')],
 
113
        )
 
114
 
 
115
    def test_circular_graph(self):
 
116
        """
 
117
        Tests a circular dependency graph.
 
118
        """
 
119
        # Build graph
 
120
        graph = MigrationGraph()
 
121
        graph.add_node(("app_a", "0001"), None)
 
122
        graph.add_node(("app_a", "0002"), None)
 
123
        graph.add_node(("app_a", "0003"), None)
 
124
        graph.add_node(("app_b", "0001"), None)
 
125
        graph.add_node(("app_b", "0002"), None)
 
126
        graph.add_dependency("app_a.0003", ("app_a", "0003"), ("app_a", "0002"))
 
127
        graph.add_dependency("app_a.0002", ("app_a", "0002"), ("app_a", "0001"))
 
128
        graph.add_dependency("app_a.0001", ("app_a", "0001"), ("app_b", "0002"))
 
129
        graph.add_dependency("app_b.0002", ("app_b", "0002"), ("app_b", "0001"))
 
130
        graph.add_dependency("app_b.0001", ("app_b", "0001"), ("app_a", "0003"))
 
131
        # Test whole graph
 
132
        self.assertRaises(
 
133
            CircularDependencyError,
 
134
            graph.forwards_plan, ("app_a", "0003"),
 
135
        )
 
136
 
 
137
    def test_plan_invalid_node(self):
 
138
        """
 
139
        Tests for forwards/backwards_plan of nonexistent node.
 
140
        """
 
141
        graph = MigrationGraph()
 
142
        message = "Node ('app_b', '0001') not a valid node"
 
143
 
 
144
        with self.assertRaisesMessage(ValueError, message):
 
145
            graph.forwards_plan(("app_b", "0001"))
 
146
 
 
147
        with self.assertRaisesMessage(ValueError, message):
 
148
            graph.backwards_plan(("app_b", "0001"))
 
149
 
 
150
    def test_missing_parent_nodes(self):
 
151
        """
 
152
        Tests for missing parent nodes.
 
153
        """
 
154
        # Build graph
 
155
        graph = MigrationGraph()
 
156
        graph.add_node(("app_a", "0001"), None)
 
157
        graph.add_node(("app_a", "0002"), None)
 
158
        graph.add_node(("app_a", "0003"), None)
 
159
        graph.add_node(("app_b", "0001"), None)
 
160
        graph.add_dependency("app_a.0003", ("app_a", "0003"), ("app_a", "0002"))
 
161
        graph.add_dependency("app_a.0002", ("app_a", "0002"), ("app_a", "0001"))
 
162
        with self.assertRaisesMessage(KeyError, "Migration app_a.0001 dependencies references nonexistent parent node ('app_b', '0002')"):
 
163
            graph.add_dependency("app_a.0001", ("app_a", "0001"), ("app_b", "0002"))
 
164
 
 
165
    def test_missing_child_nodes(self):
 
166
        """
 
167
        Tests for missing child nodes.
 
168
        """
 
169
        # Build graph
 
170
        graph = MigrationGraph()
 
171
        graph.add_node(("app_a", "0001"), None)
 
172
        with self.assertRaisesMessage(KeyError, "Migration app_a.0002 dependencies references nonexistent child node ('app_a', '0002')"):
 
173
            graph.add_dependency("app_a.0002", ("app_a", "0002"), ("app_a", "0001"))