37
37
('python-nocache', {'module': _known_graph_py, 'do_cache': False}),
39
39
suite = loader.suiteClass()
40
if compiled_known_graph_feature.available():
41
scenarios.append(('C', {'module': compiled_known_graph_feature.module,
43
caching_scenarios.append(
44
('C-nocache', {'module': compiled_known_graph_feature.module,
40
if CompiledKnownGraphFeature.available():
41
from bzrlib import _known_graph_pyx
42
scenarios.append(('C', {'module': _known_graph_pyx, 'do_cache': True}))
43
caching_scenarios.append(('C-nocache',
44
{'module': _known_graph_pyx, 'do_cache': False}))
47
46
# the compiled module isn't available, so we add a failing test
48
47
class FailWithoutFeature(tests.TestCase):
49
48
def test_fail(self):
50
self.requireFeature(compiled_known_graph_feature)
49
self.requireFeature(CompiledKnownGraphFeature)
51
50
suite.addTest(loader.loadTestsFromTestCase(FailWithoutFeature))
52
51
# TestKnownGraphHeads needs to be permutated with and without caching.
53
52
# All other TestKnownGraph tests only need to be tested across module
90
100
def test_children_ancestry1(self):
91
101
graph = self.make_known_graph(test_graph.ancestry_1)
92
self.assertEqual(['rev1'], graph.get_child_keys(NULL_REVISION))
102
self.assertEqual(['rev1'], graph._nodes[NULL_REVISION].child_keys)
93
103
self.assertEqual(['rev2a', 'rev2b'],
94
sorted(graph.get_child_keys('rev1')))
95
self.assertEqual(['rev3'], graph.get_child_keys('rev2a'))
96
self.assertEqual(['rev4'], graph.get_child_keys('rev3'))
97
self.assertEqual(['rev4'], graph.get_child_keys('rev2b'))
98
self.assertRaises(KeyError, graph.get_child_keys, 'not_in_graph')
100
def test_parent_ancestry1(self):
101
graph = self.make_known_graph(test_graph.ancestry_1)
102
self.assertEqual([NULL_REVISION], graph.get_parent_keys('rev1'))
103
self.assertEqual(['rev1'], graph.get_parent_keys('rev2a'))
104
self.assertEqual(['rev1'], graph.get_parent_keys('rev2b'))
105
self.assertEqual(['rev2a'], graph.get_parent_keys('rev3'))
106
self.assertEqual(['rev2b', 'rev3'],
107
sorted(graph.get_parent_keys('rev4')))
108
self.assertRaises(KeyError, graph.get_child_keys, 'not_in_graph')
110
def test_parent_with_ghost(self):
111
graph = self.make_known_graph(test_graph.with_ghost)
112
self.assertEqual(None, graph.get_parent_keys('g'))
104
sorted(graph._nodes['rev1'].child_keys))
105
self.assertEqual(['rev3'], sorted(graph._nodes['rev2a'].child_keys))
106
self.assertEqual(['rev4'], sorted(graph._nodes['rev3'].child_keys))
107
self.assertEqual(['rev4'], sorted(graph._nodes['rev2b'].child_keys))
114
109
def test_gdfo_ancestry_1(self):
115
110
graph = self.make_known_graph(test_graph.ancestry_1)
144
139
self.assertGDFO(graph, 'a', 5)
145
140
self.assertGDFO(graph, 'c', 5)
147
def test_add_existing_node(self):
148
graph = self.make_known_graph(test_graph.ancestry_1)
149
# Add a node that already exists with identical content
151
self.assertGDFO(graph, 'rev4', 5)
152
graph.add_node('rev4', ['rev3', 'rev2b'])
153
self.assertGDFO(graph, 'rev4', 5)
154
# This also works if we use a tuple rather than a list
155
graph.add_node('rev4', ('rev3', 'rev2b'))
157
def test_add_existing_node_mismatched_parents(self):
158
graph = self.make_known_graph(test_graph.ancestry_1)
159
self.assertRaises(ValueError, graph.add_node, 'rev4',
162
def test_add_node_with_ghost_parent(self):
163
graph = self.make_known_graph(test_graph.ancestry_1)
164
graph.add_node('rev5', ['rev2b', 'revGhost'])
165
self.assertGDFO(graph, 'rev5', 4)
166
self.assertGDFO(graph, 'revGhost', 1)
168
def test_add_new_root(self):
169
graph = self.make_known_graph(test_graph.ancestry_1)
170
graph.add_node('rev5', [])
171
self.assertGDFO(graph, 'rev5', 1)
173
def test_add_with_all_ghost_parents(self):
174
graph = self.make_known_graph(test_graph.ancestry_1)
175
graph.add_node('rev5', ['ghost'])
176
self.assertGDFO(graph, 'rev5', 2)
177
self.assertGDFO(graph, 'ghost', 1)
179
def test_gdfo_after_add_node(self):
180
graph = self.make_known_graph(test_graph.ancestry_1)
181
self.assertEqual([], graph.get_child_keys('rev4'))
182
graph.add_node('rev5', ['rev4'])
183
self.assertEqual(['rev4'], graph.get_parent_keys('rev5'))
184
self.assertEqual(['rev5'], graph.get_child_keys('rev4'))
185
self.assertEqual([], graph.get_child_keys('rev5'))
186
self.assertGDFO(graph, 'rev5', 6)
187
graph.add_node('rev6', ['rev2b'])
188
graph.add_node('rev7', ['rev6'])
189
graph.add_node('rev8', ['rev7', 'rev5'])
190
self.assertGDFO(graph, 'rev5', 6)
191
self.assertGDFO(graph, 'rev6', 4)
192
self.assertGDFO(graph, 'rev7', 5)
193
self.assertGDFO(graph, 'rev8', 7)
195
def test_fill_in_ghost(self):
196
graph = self.make_known_graph(test_graph.with_ghost)
197
# Add in a couple nodes and then fill in the 'ghost' so that it should
198
# cause renumbering of children nodes
199
graph.add_node('x', [])
200
graph.add_node('y', ['x'])
201
graph.add_node('z', ['y'])
202
graph.add_node('g', ['z'])
203
self.assertGDFO(graph, 'f', 2)
204
self.assertGDFO(graph, 'e', 3)
205
self.assertGDFO(graph, 'x', 1)
206
self.assertGDFO(graph, 'y', 2)
207
self.assertGDFO(graph, 'z', 3)
208
self.assertGDFO(graph, 'g', 4)
209
self.assertGDFO(graph, 'b', 4)
210
self.assertGDFO(graph, 'd', 5)
211
self.assertGDFO(graph, 'a', 5)
212
self.assertGDFO(graph, 'c', 6)
215
143
class TestKnownGraphHeads(TestCaseWithKnownGraph):
853
class TestKnownGraphStableReverseTopoSort(TestCaseWithKnownGraph):
854
"""Test the sort order returned by gc_sort."""
856
def assertSorted(self, expected, parent_map):
857
graph = self.make_known_graph(parent_map)
858
value = graph.gc_sort()
859
if expected != value:
860
self.assertEqualDiff(pprint.pformat(expected),
861
pprint.pformat(value))
863
def test_empty(self):
864
self.assertSorted([], {})
866
def test_single(self):
867
self.assertSorted(['a'], {'a':()})
868
self.assertSorted([('a',)], {('a',):()})
869
self.assertSorted([('F', 'a')], {('F', 'a'):()})
871
def test_linear(self):
872
self.assertSorted(['c', 'b', 'a'], {'a':(), 'b':('a',), 'c':('b',)})
873
self.assertSorted([('c',), ('b',), ('a',)],
874
{('a',):(), ('b',): (('a',),), ('c',): (('b',),)})
875
self.assertSorted([('F', 'c'), ('F', 'b'), ('F', 'a')],
876
{('F', 'a'):(), ('F', 'b'): (('F', 'a'),),
877
('F', 'c'): (('F', 'b'),)})
879
def test_mixed_ancestries(self):
880
# Each prefix should be sorted separately
881
self.assertSorted([('F', 'c'), ('F', 'b'), ('F', 'a'),
882
('G', 'c'), ('G', 'b'), ('G', 'a'),
883
('Q', 'c'), ('Q', 'b'), ('Q', 'a'),
885
{('F', 'a'):(), ('F', 'b'): (('F', 'a'),),
886
('F', 'c'): (('F', 'b'),),
887
('G', 'a'):(), ('G', 'b'): (('G', 'a'),),
888
('G', 'c'): (('G', 'b'),),
889
('Q', 'a'):(), ('Q', 'b'): (('Q', 'a'),),
890
('Q', 'c'): (('Q', 'b'),),
893
def test_stable_sorting(self):
894
# the sort order should be stable even when extra nodes are added
895
self.assertSorted(['b', 'c', 'a'],
896
{'a':(), 'b':('a',), 'c':('a',)})
897
self.assertSorted(['b', 'c', 'd', 'a'],
898
{'a':(), 'b':('a',), 'c':('a',), 'd':('a',)})
899
self.assertSorted(['b', 'c', 'd', 'a'],
900
{'a':(), 'b':('a',), 'c':('a',), 'd':('a',)})
901
self.assertSorted(['Z', 'b', 'c', 'd', 'a'],
902
{'a':(), 'b':('a',), 'c':('a',), 'd':('a',),
904
self.assertSorted(['e', 'b', 'c', 'f', 'Z', 'd', 'a'],
905
{'a':(), 'b':('a',), 'c':('a',), 'd':('a',),
911
def test_skip_ghost(self):
912
self.assertSorted(['b', 'c', 'a'],
913
{'a':(), 'b':('a', 'ghost'), 'c':('a',)})
915
def test_skip_mainline_ghost(self):
916
self.assertSorted(['b', 'c', 'a'],
917
{'a':(), 'b':('ghost', 'a'), 'c':('a',)})