1011
1014
search = graph._make_breadth_first_searcher(['head'])
1012
1015
# At the start, nothing has been seen, to its all excluded:
1013
1016
result = search.get_result()
1014
self.assertEqual((set(['head']), set(['head']), 0),
1017
self.assertEqual(('search', set(['head']), set(['head']), 0),
1015
1018
result.get_recipe())
1016
1019
self.assertEqual(set(), result.get_keys())
1017
1020
self.assertEqual(set(), search.seen)
1203
1206
self.assertRaises(StopIteration, search.next)
1204
1207
self.assertEqual(set(['head', 'ghost', NULL_REVISION]), search.seen)
1205
1208
result = search.get_result()
1206
self.assertEqual((set(['ghost', 'head']), set(['ghost']), 2),
1209
self.assertEqual(('search', set(['ghost', 'head']), set(['ghost']), 2),
1207
1210
result.get_recipe())
1208
1211
self.assertEqual(set(['head', NULL_REVISION]), result.get_keys())
1209
1212
# using next_with_ghosts:
1212
1215
self.assertRaises(StopIteration, search.next)
1213
1216
self.assertEqual(set(['head', 'ghost', NULL_REVISION]), search.seen)
1214
1217
result = search.get_result()
1215
self.assertEqual((set(['ghost', 'head']), set(['ghost']), 2),
1218
self.assertEqual(('search', set(['ghost', 'head']), set(['ghost']), 2),
1216
1219
result.get_recipe())
1217
1220
self.assertEqual(set(['head', NULL_REVISION]), result.get_keys())
1424
1432
# only present 1 time.
1425
1433
self.assertEqual(['a', 'b'], sorted(self.inst_pp.calls))
1435
def test_note_missing_key(self):
1436
"""After noting that a key is missing it is cached."""
1437
self.caching_pp.note_missing_key('b')
1438
self.assertEqual({}, self.caching_pp.get_parent_map(['b']))
1439
self.assertEqual([], self.inst_pp.calls)
1440
self.assertEqual(set(['b']), self.caching_pp.missing_keys)
1428
1443
class TestCachingParentsProviderExtras(tests.TestCaseWithTransport):
1429
1444
"""Test the behaviour when parents are provided that were not requested."""
1540
1555
repo = builder.get_branch().repository
1541
1556
repo.lock_read()
1542
1557
self.addCleanup(repo.unlock)
1543
par = _mod_graph.PendingAncestryResult(['rev-2'], repo)
1544
self.assertEqual(set(['rev-1', 'rev-2']), set(par.get_keys()))
1558
result = _mod_graph.PendingAncestryResult(['rev-2'], repo)
1559
self.assertEqual(set(['rev-1', 'rev-2']), set(result.get_keys()))
1546
1561
def test_get_keys_excludes_null(self):
1547
1562
# Make a 'graph' with an iter_ancestry that returns NULL_REVISION
1550
1565
class StubGraph(object):
1551
1566
def iter_ancestry(self, keys):
1552
1567
return [(NULL_REVISION, ()), ('foo', (NULL_REVISION,))]
1553
par = _mod_graph.PendingAncestryResult(['rev-3'], None)
1554
par_keys = par._get_keys(StubGraph())
1568
result = _mod_graph.PendingAncestryResult(['rev-3'], None)
1569
result_keys = result._get_keys(StubGraph())
1555
1570
# Only the non-null keys from the ancestry appear.
1556
self.assertEqual(set(['foo']), set(par_keys))
1571
self.assertEqual(set(['foo']), set(result_keys))
1574
class TestPendingAncestryResultRefine(TestGraphBase):
1576
def test_refine(self):
1577
# Used when pulling from a stacked repository, so test some revisions
1578
# being satisfied from the stacking branch.
1579
g = self.make_graph(
1580
{"tip":["mid"], "mid":["base"], "tag":["base"],
1581
"base":[NULL_REVISION], NULL_REVISION:[]})
1582
result = _mod_graph.PendingAncestryResult(['tip', 'tag'], None)
1583
result = result.refine(set(['tip']), set(['mid']))
1584
self.assertEqual(set(['mid', 'tag']), result.heads)
1585
result = result.refine(set(['mid', 'tag', 'base']),
1586
set([NULL_REVISION]))
1587
self.assertEqual(set([NULL_REVISION]), result.heads)
1588
self.assertTrue(result.is_empty())
1591
class TestSearchResultRefine(TestGraphBase):
1593
def test_refine(self):
1594
# Used when pulling from a stacked repository, so test some revisions
1595
# being satisfied from the stacking branch.
1596
g = self.make_graph(
1597
{"tip":["mid"], "mid":["base"], "tag":["base"],
1598
"base":[NULL_REVISION], NULL_REVISION:[]})
1599
result = _mod_graph.SearchResult(set(['tip', 'tag']),
1600
set([NULL_REVISION]), 4, set(['tip', 'mid', 'tag', 'base']))
1601
result = result.refine(set(['tip']), set(['mid']))
1602
recipe = result.get_recipe()
1603
# We should be starting from tag (original head) and mid (seen ref)
1604
self.assertEqual(set(['mid', 'tag']), recipe[1])
1605
# We should be stopping at NULL (original stop) and tip (seen head)
1606
self.assertEqual(set([NULL_REVISION, 'tip']), recipe[2])
1607
self.assertEqual(3, recipe[3])
1608
result = result.refine(set(['mid', 'tag', 'base']),
1609
set([NULL_REVISION]))
1610
recipe = result.get_recipe()
1611
# We should be starting from nothing (NULL was known as a cut point)
1612
self.assertEqual(set([]), recipe[1])
1613
# We should be stopping at NULL (original stop) and tip (seen head) and
1614
# tag (seen head) and mid(seen mid-point head). We could come back and
1615
# define this as not including mid, for minimal results, but it is
1616
# still 'correct' to include mid, and simpler/easier.
1617
self.assertEqual(set([NULL_REVISION, 'tip', 'tag', 'mid']), recipe[2])
1618
self.assertEqual(0, recipe[3])
1619
self.assertTrue(result.is_empty())