21
21
from bzrlib import (
26
27
from bzrlib.tests import test_graph
27
28
from bzrlib.revision import NULL_REVISION
28
from bzrlib.tests.scenarios import load_tests_apply_scenarios
31
def caching_scenarios():
31
def load_tests(standard_tests, module, loader):
32
"""Parameterize tests for all versions of groupcompress."""
33
34
('python', {'module': _known_graph_py, 'do_cache': True}),
35
if compiled_known_graph_feature.available():
36
scenarios.append(('C', {'module': compiled_known_graph_feature.module,
41
def non_caching_scenarios():
43
37
('python-nocache', {'module': _known_graph_py, 'do_cache': False}),
45
if compiled_known_graph_feature.available():
47
('C-nocache', {'module': compiled_known_graph_feature.module,
52
load_tests = load_tests_apply_scenarios
55
compiled_known_graph_feature = tests.ModuleAvailableFeature(
56
'bzrlib._known_graph_pyx')
39
suite = loader.suiteClass()
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}))
46
# the compiled module isn't available, so we add a failing test
47
class FailWithoutFeature(tests.TestCase):
49
self.requireFeature(CompiledKnownGraphFeature)
50
suite.addTest(loader.loadTestsFromTestCase(FailWithoutFeature))
51
# TestKnownGraphHeads needs to be permutated with and without caching.
52
# All other TestKnownGraph tests only need to be tested across module
53
heads_suite, other_suite = tests.split_suite_by_condition(
54
standard_tests, tests.condition_isinstance(TestKnownGraphHeads))
55
suite = tests.multiply_tests(other_suite, scenarios, suite)
56
suite = tests.multiply_tests(heads_suite, scenarios + caching_scenarios,
61
class _CompiledKnownGraphFeature(tests.Feature):
65
import bzrlib._known_graph_pyx
70
def feature_name(self):
71
return 'bzrlib._known_graph_pyx'
73
CompiledKnownGraphFeature = _CompiledKnownGraphFeature()
138
154
self.assertGDFO(graph, 'a', 5)
139
155
self.assertGDFO(graph, 'c', 5)
141
def test_add_existing_node(self):
142
graph = self.make_known_graph(test_graph.ancestry_1)
143
# Add a node that already exists with identical content
145
self.assertGDFO(graph, 'rev4', 5)
146
graph.add_node('rev4', ['rev3', 'rev2b'])
147
self.assertGDFO(graph, 'rev4', 5)
148
# This also works if we use a tuple rather than a list
149
graph.add_node('rev4', ('rev3', 'rev2b'))
151
def test_add_existing_node_mismatched_parents(self):
152
graph = self.make_known_graph(test_graph.ancestry_1)
153
self.assertRaises(ValueError, graph.add_node, 'rev4',
156
def test_add_node_with_ghost_parent(self):
157
graph = self.make_known_graph(test_graph.ancestry_1)
158
graph.add_node('rev5', ['rev2b', 'revGhost'])
159
self.assertGDFO(graph, 'rev5', 4)
160
self.assertGDFO(graph, 'revGhost', 1)
162
def test_add_new_root(self):
163
graph = self.make_known_graph(test_graph.ancestry_1)
164
graph.add_node('rev5', [])
165
self.assertGDFO(graph, 'rev5', 1)
167
def test_add_with_all_ghost_parents(self):
168
graph = self.make_known_graph(test_graph.ancestry_1)
169
graph.add_node('rev5', ['ghost'])
170
self.assertGDFO(graph, 'rev5', 2)
171
self.assertGDFO(graph, 'ghost', 1)
173
def test_gdfo_after_add_node(self):
174
graph = self.make_known_graph(test_graph.ancestry_1)
175
self.assertEqual([], graph.get_child_keys('rev4'))
176
graph.add_node('rev5', ['rev4'])
177
self.assertEqual(['rev4'], graph.get_parent_keys('rev5'))
178
self.assertEqual(['rev5'], graph.get_child_keys('rev4'))
179
self.assertEqual([], graph.get_child_keys('rev5'))
180
self.assertGDFO(graph, 'rev5', 6)
181
graph.add_node('rev6', ['rev2b'])
182
graph.add_node('rev7', ['rev6'])
183
graph.add_node('rev8', ['rev7', 'rev5'])
184
self.assertGDFO(graph, 'rev5', 6)
185
self.assertGDFO(graph, 'rev6', 4)
186
self.assertGDFO(graph, 'rev7', 5)
187
self.assertGDFO(graph, 'rev8', 7)
189
def test_fill_in_ghost(self):
190
graph = self.make_known_graph(test_graph.with_ghost)
191
# Add in a couple nodes and then fill in the 'ghost' so that it should
192
# cause renumbering of children nodes
193
graph.add_node('x', [])
194
graph.add_node('y', ['x'])
195
graph.add_node('z', ['y'])
196
graph.add_node('g', ['z'])
197
self.assertGDFO(graph, 'f', 2)
198
self.assertGDFO(graph, 'e', 3)
199
self.assertGDFO(graph, 'x', 1)
200
self.assertGDFO(graph, 'y', 2)
201
self.assertGDFO(graph, 'z', 3)
202
self.assertGDFO(graph, 'g', 4)
203
self.assertGDFO(graph, 'b', 4)
204
self.assertGDFO(graph, 'd', 5)
205
self.assertGDFO(graph, 'a', 5)
206
self.assertGDFO(graph, 'c', 6)
209
158
class TestKnownGraphHeads(TestCaseWithKnownGraph):
211
scenarios = caching_scenarios() + non_caching_scenarios()
212
160
do_cache = None # Set by load_tests
214
162
def test_heads_null(self):
312
260
self.assertEqual(set(['a', 'c']), graph.heads(['a', 'c', 'e', 'g']))
313
261
self.assertEqual(set(['a', 'c']), graph.heads(['a', 'c', 'f']))
315
def test_filling_in_ghosts_resets_head_cache(self):
316
graph = self.make_known_graph(test_graph.with_ghost)
317
self.assertEqual(set(['e', 'g']), graph.heads(['e', 'g']))
318
# 'g' is filled in, and decends from 'e', so the heads result is now
320
graph.add_node('g', ['e'])
321
self.assertEqual(set(['g']), graph.heads(['e', 'g']))
324
264
class TestKnownGraphTopoSort(TestCaseWithKnownGraph):