120
120
'rev2b': ['rev1'], 'rev2c': ['rev1'],
121
121
'rev3a': ['rev2a', 'rev2b'], 'rev3b': ['rev2b', 'rev2c']}
133
boundary = {'a': ['b'], 'c': ['b', 'd'], 'b':['e'], 'd':['e'], 'e': ['f'],
137
class InstrumentedParentsProvider(object):
139
def __init__(self, parents_provider):
141
self._real_parents_provider = parents_provider
143
def get_parents(self, nodes):
144
self.calls.extend(nodes)
145
return self._real_parents_provider.get_parents(nodes)
148
class DictParentsProvider(object):
150
def __init__(self, ancestry):
151
self.ancestry = ancestry
154
return 'DictParentsProvider(%r)' % self.ancestry
156
def get_parents(self, revisions):
157
return [self.ancestry.get(r, None) for r in revisions]
124
160
class TestGraph(TestCaseWithMemoryTransport):
268
304
def test_stacked_parents_provider(self):
270
class ParentsProvider(object):
272
def __init__(self, ancestry):
273
self.ancestry = ancestry
275
def get_parents(self, revisions):
276
return [self.ancestry.get(r, None) for r in revisions]
278
parents1 = ParentsProvider({'rev2': ['rev3']})
279
parents2 = ParentsProvider({'rev1': ['rev4']})
280
stacked = graph._StackedParentsProvider([parents1, parents2])
306
parents1 = DictParentsProvider({'rev2': ['rev3']})
307
parents2 = DictParentsProvider({'rev1': ['rev4']})
308
stacked = _mod_graph._StackedParentsProvider([parents1, parents2])
281
309
self.assertEqual([['rev4',], ['rev3']],
282
310
stacked.get_parents(['rev1', 'rev2']))
283
311
self.assertEqual([['rev3',], ['rev4']],
294
322
self.assertEqual(set(args), set(topo_args))
295
323
self.assertTrue(topo_args.index('rev2a') > topo_args.index('rev1'))
296
324
self.assertTrue(topo_args.index('rev2a') < topo_args.index('rev3'))
326
def test_is_ancestor(self):
327
graph = self.make_graph(ancestry_1)
328
self.assertEqual(True, graph.is_ancestor('null:', 'null:'))
329
self.assertEqual(True, graph.is_ancestor('null:', 'rev1'))
330
self.assertEqual(False, graph.is_ancestor('rev1', 'null:'))
331
self.assertEqual(True, graph.is_ancestor('null:', 'rev4'))
332
self.assertEqual(False, graph.is_ancestor('rev4', 'null:'))
333
self.assertEqual(False, graph.is_ancestor('rev4', 'rev2b'))
334
self.assertEqual(True, graph.is_ancestor('rev2b', 'rev4'))
335
self.assertEqual(False, graph.is_ancestor('rev2b', 'rev3'))
336
self.assertEqual(False, graph.is_ancestor('rev3', 'rev2b'))
337
instrumented_provider = InstrumentedParentsProvider(graph)
338
instrumented_graph = _mod_graph.Graph(instrumented_provider)
339
instrumented_graph.is_ancestor('rev2a', 'rev2b')
340
self.assertTrue('null:' not in instrumented_provider.calls)
342
def test_is_ancestor_boundary(self):
343
"""Ensure that we avoid searching the whole graph.
345
This requires searching through b as a common ancestor, so we
346
can identify that e is common.
348
graph = self.make_graph(boundary)
349
instrumented_provider = InstrumentedParentsProvider(graph)
350
graph = _mod_graph.Graph(instrumented_provider)
351
self.assertFalse(graph.is_ancestor('a', 'c'))
352
self.assertTrue('null:' not in instrumented_provider.calls)
354
def test_filter_candidate_lca(self):
355
"""Test filter_candidate_lca for a corner case
357
This tests the case where we encounter the end of iteration for 'e'
358
in the same pass as we discover that 'd' is an ancestor of 'e', and
359
therefore 'e' can't be an lca.
361
To compensate for different dict orderings on other Python
362
implementations, we mirror 'd' and 'e' with 'b' and 'a'.
364
# This test is sensitive to the iteration order of dicts. It will
365
# pass incorrectly if 'e' and 'a' sort before 'c'
374
graph = self.make_graph({'c': ['b', 'd'], 'd': ['e'], 'b': ['a'],
375
'a': [NULL_REVISION], 'e': [NULL_REVISION]})
376
self.assertEqual(['c'], graph._filter_candidate_lca(['a', 'c', 'e']))