1601
1613
(('tip',), 'line-delta', (None, 0, 100), [('parent',)])])
1602
1614
self.assertEqual([], self.caught_entries)
1616
def make_g_index_missing_compression_parent(self):
1617
graph_index = self.make_g_index('missing_comp', 2,
1618
[(('tip', ), ' 100 78',
1619
([('missing-parent', ), ('ghost', )], [('missing-parent', )]))])
1622
def make_g_index_no_external_refs(self):
1623
graph_index = self.make_g_index('no_external_refs', 2,
1624
[(('rev', ), ' 100 78',
1625
([('parent', ), ('ghost', )], []))])
1628
def test_add_good_unvalidated_index(self):
1629
unvalidated = self.make_g_index_no_external_refs()
1630
combined = CombinedGraphIndex([unvalidated])
1631
index = _KnitGraphIndex(combined, lambda: True, deltas=True)
1632
index.scan_unvalidated_index(unvalidated)
1633
self.assertEqual(frozenset(), index.get_missing_compression_parents())
1635
def test_add_incomplete_unvalidated_index(self):
1636
unvalidated = self.make_g_index_missing_compression_parent()
1637
combined = CombinedGraphIndex([unvalidated])
1638
index = _KnitGraphIndex(combined, lambda: True, deltas=True)
1639
index.scan_unvalidated_index(unvalidated)
1640
# This also checks that its only the compression parent that is
1641
# examined, otherwise 'ghost' would also be reported as a missing
1644
frozenset([('missing-parent',)]),
1645
index.get_missing_compression_parents())
1647
def test_add_unvalidated_index_with_present_external_references(self):
1648
index = self.two_graph_index(deltas=True)
1649
# Ugly hack to get at one of the underlying GraphIndex objects that
1650
# two_graph_index built.
1651
unvalidated = index._graph_index._indices[1]
1652
# 'parent' is an external ref of _indices[1] (unvalidated), but is
1653
# present in _indices[0].
1654
index.scan_unvalidated_index(unvalidated)
1655
self.assertEqual(frozenset(), index.get_missing_compression_parents())
1657
def make_new_missing_parent_g_index(self, name):
1658
missing_parent = name + '-missing-parent'
1659
graph_index = self.make_g_index(name, 2,
1660
[((name + 'tip', ), ' 100 78',
1661
([(missing_parent, ), ('ghost', )], [(missing_parent, )]))])
1664
def test_add_mulitiple_unvalidated_indices_with_missing_parents(self):
1665
g_index_1 = self.make_new_missing_parent_g_index('one')
1666
g_index_2 = self.make_new_missing_parent_g_index('two')
1667
combined = CombinedGraphIndex([g_index_1, g_index_2])
1668
index = _KnitGraphIndex(combined, lambda: True, deltas=True)
1669
index.scan_unvalidated_index(g_index_1)
1670
index.scan_unvalidated_index(g_index_2)
1672
frozenset([('one-missing-parent',), ('two-missing-parent',)]),
1673
index.get_missing_compression_parents())
1675
def test_add_mulitiple_unvalidated_indices_with_mutual_dependencies(self):
1676
graph_index_a = self.make_g_index('one', 2,
1677
[(('parent-one', ), ' 100 78', ([('non-compression-parent',)], [])),
1678
(('child-of-two', ), ' 100 78',
1679
([('parent-two',)], [('parent-two',)]))])
1680
graph_index_b = self.make_g_index('two', 2,
1681
[(('parent-two', ), ' 100 78', ([('non-compression-parent',)], [])),
1682
(('child-of-one', ), ' 100 78',
1683
([('parent-one',)], [('parent-one',)]))])
1684
combined = CombinedGraphIndex([graph_index_a, graph_index_b])
1685
index = _KnitGraphIndex(combined, lambda: True, deltas=True)
1686
index.scan_unvalidated_index(graph_index_a)
1687
index.scan_unvalidated_index(graph_index_b)
1689
frozenset([]), index.get_missing_compression_parents())
1605
1692
class TestNoParentsGraphIndexKnit(KnitTests):
1606
1693
"""Tests for knits using _KnitGraphIndex with no parents."""
2173
2271
self.assertEqual(set([key_left, key_right]), set(last_call[1]))
2174
2272
self.assertEqual('unordered', last_call[2])
2175
2273
self.assertEqual(True, last_call[3])
2276
class TestNetworkBehaviour(KnitTests):
2277
"""Tests for getting data out of/into knits over the network."""
2279
def test_include_delta_closure_generates_a_knit_delta_closure(self):
2280
vf = self.make_test_knit(name='test')
2281
# put in three texts, giving ft, delta, delta
2282
vf.add_lines(('base',), (), ['base\n', 'content\n'])
2283
vf.add_lines(('d1',), (('base',),), ['d1\n'])
2284
vf.add_lines(('d2',), (('d1',),), ['d2\n'])
2285
# But heuristics could interfere, so check what happened:
2286
self.assertEqual(['knit-ft-gz', 'knit-delta-gz', 'knit-delta-gz'],
2287
[record.storage_kind for record in
2288
vf.get_record_stream([('base',), ('d1',), ('d2',)],
2289
'topological', False)])
2290
# generate a stream of just the deltas include_delta_closure=True,
2291
# serialise to the network, and check that we get a delta closure on the wire.
2292
stream = vf.get_record_stream([('d1',), ('d2',)], 'topological', True)
2293
netb = [record.get_bytes_as(record.storage_kind) for record in stream]
2294
# The first bytes should be a memo from _ContentMapGenerator, and the
2295
# second bytes should be empty (because its a API proxy not something
2296
# for wire serialisation.
2297
self.assertEqual('', netb[1])
2299
kind, line_end = network_bytes_to_kind_and_offset(bytes)
2300
self.assertEqual('knit-delta-closure', kind)
2303
class TestContentMapGenerator(KnitTests):
2304
"""Tests for ContentMapGenerator"""
2306
def test_get_record_stream_gives_records(self):
2307
vf = self.make_test_knit(name='test')
2308
# put in three texts, giving ft, delta, delta
2309
vf.add_lines(('base',), (), ['base\n', 'content\n'])
2310
vf.add_lines(('d1',), (('base',),), ['d1\n'])
2311
vf.add_lines(('d2',), (('d1',),), ['d2\n'])
2312
keys = [('d1',), ('d2',)]
2313
generator = _VFContentMapGenerator(vf, keys,
2314
global_map=vf.get_parent_map(keys))
2315
for record in generator.get_record_stream():
2316
if record.key == ('d1',):
2317
self.assertEqual('d1\n', record.get_bytes_as('fulltext'))
2319
self.assertEqual('d2\n', record.get_bytes_as('fulltext'))
2321
def test_get_record_stream_kinds_are_raw(self):
2322
vf = self.make_test_knit(name='test')
2323
# put in three texts, giving ft, delta, delta
2324
vf.add_lines(('base',), (), ['base\n', 'content\n'])
2325
vf.add_lines(('d1',), (('base',),), ['d1\n'])
2326
vf.add_lines(('d2',), (('d1',),), ['d2\n'])
2327
keys = [('base',), ('d1',), ('d2',)]
2328
generator = _VFContentMapGenerator(vf, keys,
2329
global_map=vf.get_parent_map(keys))
2330
kinds = {('base',): 'knit-delta-closure',
2331
('d1',): 'knit-delta-closure-ref',
2332
('d2',): 'knit-delta-closure-ref',
2334
for record in generator.get_record_stream():
2335
self.assertEqual(kinds[record.key], record.storage_kind)