~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/tests/test_knit.py

Reconcile NEWS

Show diffs side-by-side

added added

removed removed

Lines of Context:
37
37
from bzrlib.index import *
38
38
from bzrlib.knit import (
39
39
    AnnotatedKnitContent,
 
40
    DATA_SUFFIX,
 
41
    INDEX_SUFFIX,
40
42
    KnitContent,
41
43
    KnitGraphIndex,
42
44
    KnitVersionedFile,
45
47
    _KnitAccess,
46
48
    _KnitData,
47
49
    _KnitIndex,
 
50
    make_file_knit,
48
51
    _PackAccess,
49
52
    PlainKnitContent,
50
53
    _StreamAccess,
53
56
    KnitSequenceMatcher,
54
57
    )
55
58
from bzrlib.osutils import split_lines
 
59
from bzrlib.symbol_versioning import one_four
56
60
from bzrlib.tests import (
57
61
    Feature,
58
62
    TestCase,
158
162
        self.assertEqual(content.annotate(),
159
163
            [("bogus", "text1"), ("bogus", "text2")])
160
164
 
161
 
    def test_annotate_iter(self):
162
 
        content = self._make_content([])
163
 
        it = content.annotate_iter()
164
 
        self.assertRaises(StopIteration, it.next)
165
 
 
166
 
        content = self._make_content([("bogus", "text1"), ("bogus", "text2")])
167
 
        it = content.annotate_iter()
168
 
        self.assertEqual(it.next(), ("bogus", "text1"))
169
 
        self.assertEqual(it.next(), ("bogus", "text2"))
170
 
        self.assertRaises(StopIteration, it.next)
171
 
 
172
165
    def test_line_delta(self):
173
166
        content1 = self._make_content([("", "a"), ("", "b")])
174
167
        content2 = self._make_content([("", "a"), ("", "a"), ("", "c")])
196
189
        self.assertEqual(content.annotate(),
197
190
            [("origin1", "text1"), ("origin2", "text2")])
198
191
 
199
 
    def test_annotate_iter(self):
200
 
        content = self._make_content([])
201
 
        it = content.annotate_iter()
202
 
        self.assertRaises(StopIteration, it.next)
203
 
 
204
 
        content = self._make_content([("origin1", "text1"), ("origin2", "text2")])
205
 
        it = content.annotate_iter()
206
 
        self.assertEqual(it.next(), ("origin1", "text1"))
207
 
        self.assertEqual(it.next(), ("origin2", "text2"))
208
 
        self.assertRaises(StopIteration, it.next)
209
 
 
210
192
    def test_line_delta(self):
211
193
        content1 = self._make_content([("", "a"), ("", "b")])
212
194
        content2 = self._make_content([("", "a"), ("", "a"), ("", "c")])
492
474
        self.addCleanup(reset)
493
475
        from bzrlib._knit_load_data_py import _load_data_py
494
476
        knit._load_data = _load_data_py
495
 
        return _KnitIndex(*args, **kwargs)
 
477
        return _KnitIndex(get_scope=lambda:None, *args, **kwargs)
496
478
 
497
479
    def test_no_such_file(self):
498
480
        transport = MockTransport()
677
659
        self.assertRaises(RevisionNotPresent,
678
660
            index.get_ancestry_with_ghosts, ["e"])
679
661
 
680
 
    def test_iter_parents(self):
681
 
        transport = MockTransport()
682
 
        index = self.get_knit_index(transport, "filename", "w", create=True)
683
 
        # no parents
684
 
        index.add_version('r0', ['option'], (None, 0, 1), [])
685
 
        # 1 parent
686
 
        index.add_version('r1', ['option'], (None, 0, 1), ['r0'])
687
 
        # 2 parents
688
 
        index.add_version('r2', ['option'], (None, 0, 1), ['r1', 'r0'])
689
 
        # XXX TODO a ghost
690
 
        # cases: each sample data individually:
691
 
        self.assertEqual(set([('r0', ())]),
692
 
            set(index.iter_parents(['r0'])))
693
 
        self.assertEqual(set([('r1', ('r0', ))]),
694
 
            set(index.iter_parents(['r1'])))
695
 
        self.assertEqual(set([('r2', ('r1', 'r0'))]),
696
 
            set(index.iter_parents(['r2'])))
697
 
        # no nodes returned for a missing node
698
 
        self.assertEqual(set(),
699
 
            set(index.iter_parents(['missing'])))
700
 
        # 1 node returned with missing nodes skipped
701
 
        self.assertEqual(set([('r1', ('r0', ))]),
702
 
            set(index.iter_parents(['ghost1', 'r1', 'ghost'])))
703
 
        # 2 nodes returned
704
 
        self.assertEqual(set([('r0', ()), ('r1', ('r0', ))]),
705
 
            set(index.iter_parents(['r0', 'r1'])))
706
 
        # 2 nodes returned, missing skipped
707
 
        self.assertEqual(set([('r0', ()), ('r1', ('r0', ))]),
708
 
            set(index.iter_parents(['a', 'r0', 'b', 'r1', 'c'])))
709
 
 
710
662
    def test_num_versions(self):
711
663
        transport = MockTransport([
712
664
            _KnitIndex.HEADER
1075
1027
        self.addCleanup(reset)
1076
1028
        from bzrlib._knit_load_data_c import _load_data_c
1077
1029
        knit._load_data = _load_data_c
1078
 
        return _KnitIndex(*args, **kwargs)
1079
 
 
 
1030
        return _KnitIndex(get_scope=lambda:None, *args, **kwargs)
1080
1031
 
1081
1032
 
1082
1033
class KnitTests(TestCaseWithTransport):
1083
1034
    """Class containing knit test helper routines."""
1084
1035
 
1085
1036
    def make_test_knit(self, annotate=False, delay_create=False, index=None,
1086
 
                       name='test'):
 
1037
                       name='test', delta=True, access_mode='w'):
1087
1038
        if not annotate:
1088
1039
            factory = KnitPlainFactory()
1089
1040
        else:
1090
1041
            factory = None
1091
 
        return KnitVersionedFile(name, get_transport('.'), access_mode='w',
1092
 
                                 factory=factory, create=True,
1093
 
                                 delay_create=delay_create, index=index)
 
1042
        if index is None:
 
1043
            index = _KnitIndex(get_transport('.'), name + INDEX_SUFFIX,
 
1044
                access_mode, create=True, file_mode=None,
 
1045
                create_parent_dir=False, delay_create=delay_create,
 
1046
                dir_mode=None, get_scope=lambda:None)
 
1047
        access = _KnitAccess(get_transport('.'), name + DATA_SUFFIX, None,
 
1048
            None, delay_create, False)
 
1049
        return KnitVersionedFile(name, get_transport('.'), factory=factory,
 
1050
            create=True, delay_create=delay_create, index=index,
 
1051
            access_method=access, delta=delta)
1094
1052
 
1095
1053
    def assertRecordContentEqual(self, knit, version_id, candidate_content):
1096
1054
        """Assert that some raw record content matches the raw record content
1115
1073
    def test_make_explicit_index(self):
1116
1074
        """We can supply an index to use."""
1117
1075
        knit = KnitVersionedFile('test', get_transport('.'),
1118
 
            index='strangelove')
 
1076
            index='strangelove', access_method="a")
1119
1077
        self.assertEqual(knit._index, 'strangelove')
1120
1078
 
1121
1079
    def test_knit_add(self):
1162
1120
        k = self.make_test_knit()
1163
1121
        k.add_lines('text-1', [], split_lines(TEXT_1))
1164
1122
        del k
1165
 
        k2 = KnitVersionedFile('test', get_transport('.'), access_mode='r', factory=KnitPlainFactory(), create=True)
 
1123
        k2 = make_file_knit('test', get_transport('.'), access_mode='r',
 
1124
            factory=KnitPlainFactory(), create=True)
1166
1125
        self.assertTrue(k2.has_version('text-1'))
1167
1126
        self.assertEqualDiff(''.join(k2.get_lines('text-1')), TEXT_1)
1168
1127
 
1190
1149
    def test_incomplete(self):
1191
1150
        """Test if texts without a ending line-end can be inserted and
1192
1151
        extracted."""
1193
 
        k = KnitVersionedFile('test', get_transport('.'), delta=False, create=True)
 
1152
        k = make_file_knit('test', get_transport('.'), delta=False, create=True)
1194
1153
        k.add_lines('text-1', [], ['a\n',    'b'  ])
1195
1154
        k.add_lines('text-2', ['text-1'], ['a\rb\n', 'b\n'])
1196
1155
        # reopening ensures maximum room for confusion
1197
 
        k = KnitVersionedFile('test', get_transport('.'), delta=False, create=True)
 
1156
        k = make_file_knit('test', get_transport('.'), delta=False, create=True)
1198
1157
        self.assertEquals(k.get_lines('text-1'), ['a\n',    'b'  ])
1199
1158
        self.assertEquals(k.get_lines('text-2'), ['a\rb\n', 'b\n'])
1200
1159
 
1222
1181
 
1223
1182
    def test_add_delta(self):
1224
1183
        """Store in knit with parents"""
1225
 
        k = KnitVersionedFile('test', get_transport('.'), factory=KnitPlainFactory(),
1226
 
            delta=True, create=True)
 
1184
        k = self.make_test_knit(annotate=False)
1227
1185
        self.add_stock_one_and_one_a(k)
1228
 
        k.clear_cache()
1229
1186
        self.assertEqualDiff(''.join(k.get_lines('text-1a')), TEXT_1A)
1230
1187
 
1231
1188
    def test_add_delta_knit_graph_index(self):
1233
1190
        index = InMemoryGraphIndex(2)
1234
1191
        knit_index = KnitGraphIndex(index, add_callback=index.add_nodes,
1235
1192
            deltas=True)
1236
 
        k = KnitVersionedFile('test', get_transport('.'),
1237
 
            delta=True, create=True, index=knit_index)
 
1193
        k = self.make_test_knit(annotate=True, index=knit_index)
1238
1194
        self.add_stock_one_and_one_a(k)
1239
 
        k.clear_cache()
1240
1195
        self.assertEqualDiff(''.join(k.get_lines('text-1a')), TEXT_1A)
1241
1196
        # check the index had the right data added.
1242
1197
        self.assertEqual(set([
1248
1203
 
1249
1204
    def test_annotate(self):
1250
1205
        """Annotations"""
1251
 
        k = KnitVersionedFile('knit', get_transport('.'), factory=KnitAnnotateFactory(),
1252
 
            delta=True, create=True)
 
1206
        k = self.make_test_knit(annotate=True, name='knit')
1253
1207
        self.insert_and_test_small_annotate(k)
1254
1208
 
1255
1209
    def insert_and_test_small_annotate(self, k):
1263
1217
 
1264
1218
    def test_annotate_fulltext(self):
1265
1219
        """Annotations"""
1266
 
        k = KnitVersionedFile('knit', get_transport('.'), factory=KnitAnnotateFactory(),
1267
 
            delta=False, create=True)
 
1220
        k = self.make_test_knit(annotate=True, name='knit', delta=False)
1268
1221
        self.insert_and_test_small_annotate(k)
1269
1222
 
1270
1223
    def test_annotate_merge_1(self):
1341
1294
        self.assertEquals(origins[2], ('text-1', 'c\n'))
1342
1295
 
1343
1296
    def _test_join_with_factories(self, k1_factory, k2_factory):
1344
 
        k1 = KnitVersionedFile('test1', get_transport('.'), factory=k1_factory, create=True)
 
1297
        k1 = make_file_knit('test1', get_transport('.'), factory=k1_factory, create=True)
1345
1298
        k1.add_lines('text-a', [], ['a1\n', 'a2\n', 'a3\n'])
1346
1299
        k1.add_lines('text-b', ['text-a'], ['a1\n', 'b2\n', 'a3\n'])
1347
1300
        k1.add_lines('text-c', [], ['c1\n', 'c2\n', 'c3\n'])
1348
1301
        k1.add_lines('text-d', ['text-c'], ['c1\n', 'd2\n', 'd3\n'])
1349
1302
        k1.add_lines('text-m', ['text-b', 'text-d'], ['a1\n', 'b2\n', 'd3\n'])
1350
 
        k2 = KnitVersionedFile('test2', get_transport('.'), factory=k2_factory, create=True)
 
1303
        k2 = make_file_knit('test2', get_transport('.'), factory=k2_factory, create=True)
1351
1304
        count = k2.join(k1, version_ids=['text-m'])
1352
1305
        self.assertEquals(count, 5)
1353
1306
        self.assertTrue(k2.has_version('text-a'))
1374
1327
        self._test_join_with_factories(KnitPlainFactory(), None)
1375
1328
 
1376
1329
    def test_reannotate(self):
1377
 
        k1 = KnitVersionedFile('knit1', get_transport('.'),
 
1330
        k1 = make_file_knit('knit1', get_transport('.'),
1378
1331
                               factory=KnitAnnotateFactory(), create=True)
1379
1332
        # 0
1380
1333
        k1.add_lines('text-a', [], ['a\n', 'b\n'])
1381
1334
        # 1
1382
1335
        k1.add_lines('text-b', ['text-a'], ['a\n', 'c\n'])
1383
1336
 
1384
 
        k2 = KnitVersionedFile('test2', get_transport('.'),
 
1337
        k2 = make_file_knit('test2', get_transport('.'),
1385
1338
                               factory=KnitAnnotateFactory(), create=True)
1386
1339
        k2.join(k1, version_ids=['text-b'])
1387
1340
 
1404
1357
 
1405
1358
    def test_get_line_delta_texts(self):
1406
1359
        """Make sure we can call get_texts on text with reused line deltas"""
1407
 
        k1 = KnitVersionedFile('test1', get_transport('.'), 
1408
 
                               factory=KnitPlainFactory(), create=True)
 
1360
        k1 = make_file_knit('test1', get_transport('.'),
 
1361
            factory=KnitPlainFactory(), create=True)
1409
1362
        for t in range(3):
1410
1363
            if t == 0:
1411
1364
                parents = []
1416
1369
        
1417
1370
    def test_iter_lines_reads_in_order(self):
1418
1371
        instrumented_t = get_transport('trace+memory:///')
1419
 
        k1 = KnitVersionedFile('id', instrumented_t, create=True, delta=True)
 
1372
        k1 = make_file_knit('id', instrumented_t, create=True, delta=True)
1420
1373
        self.assertEqual([('get', 'id.kndx',)], instrumented_t._activity)
1421
1374
        # add texts with no required ordering
1422
1375
        k1.add_lines('base', [], ['text\n'])
1423
1376
        k1.add_lines('base2', [], ['text2\n'])
1424
 
        k1.clear_cache()
1425
1377
        # clear the logged activity, but preserve the list instance in case of
1426
1378
        # clones pointing at it.
1427
1379
        del instrumented_t._activity[:]
1452
1404
            "\nrevid2 line-delta 84 82 0 :",
1453
1405
            'test.kndx')
1454
1406
        # we should be able to load this file again
1455
 
        knit = KnitVersionedFile('test', get_transport('.'), access_mode='r')
 
1407
        knit = make_file_knit('test', get_transport('.'), access_mode='r')
1456
1408
        self.assertEqual(['revid', 'revid2'], knit.versions())
1457
1409
        # write a short write to the file and ensure that its ignored
1458
1410
        indexfile = file('test.kndx', 'ab')
1459
1411
        indexfile.write('\nrevid3 line-delta 166 82 1 2 3 4 5 .phwoar:demo ')
1460
1412
        indexfile.close()
1461
1413
        # we should be able to load this file again
1462
 
        knit = KnitVersionedFile('test', get_transport('.'), access_mode='w')
 
1414
        knit = make_file_knit('test', get_transport('.'), access_mode='w')
1463
1415
        self.assertEqual(['revid', 'revid2'], knit.versions())
1464
1416
        # and add a revision with the same id the failed write had
1465
1417
        knit.add_lines('revid3', ['revid2'], ['a\n'])
1466
1418
        # and when reading it revid3 should now appear.
1467
 
        knit = KnitVersionedFile('test', get_transport('.'), access_mode='r')
 
1419
        knit = make_file_knit('test', get_transport('.'), access_mode='r')
1468
1420
        self.assertEqual(['revid', 'revid2', 'revid3'], knit.versions())
1469
1421
        self.assertEqual({'revid3':('revid2',)}, knit.get_parent_map(['revid3']))
1470
1422
 
1485
1437
        """create_parent_dir can create knits in nonexistant dirs"""
1486
1438
        # Has no effect if we don't set 'delay_create'
1487
1439
        trans = get_transport('.')
1488
 
        self.assertRaises(NoSuchFile, KnitVersionedFile, 'dir/test',
 
1440
        self.assertRaises(NoSuchFile, make_file_knit, 'dir/test',
1489
1441
                          trans, access_mode='w', factory=None,
1490
1442
                          create=True, create_parent_dir=True)
1491
1443
        # Nothing should have changed yet
1492
 
        knit = KnitVersionedFile('dir/test', trans, access_mode='w',
 
1444
        knit = make_file_knit('dir/test', trans, access_mode='w',
1493
1445
                                 factory=None, create=True,
1494
1446
                                 create_parent_dir=True,
1495
1447
                                 delay_create=True)
1510
1462
        if not trans._can_roundtrip_unix_modebits():
1511
1463
            # Can't roundtrip, so no need to run this test
1512
1464
            return
1513
 
        knit = KnitVersionedFile('dir/test', trans, access_mode='w',
1514
 
                                 factory=None, create=True,
1515
 
                                 create_parent_dir=True,
1516
 
                                 delay_create=True,
1517
 
                                 file_mode=0600,
1518
 
                                 dir_mode=0700)
 
1465
        knit = make_file_knit('dir/test', trans, access_mode='w', factory=None,
 
1466
            create=True, create_parent_dir=True, delay_create=True,
 
1467
            file_mode=0600, dir_mode=0700)
1519
1468
        knit.add_lines('revid', [], ['a\n'])
1520
1469
        self.assertTransportMode(trans, 'dir', 0700)
1521
1470
        self.assertTransportMode(trans, 'dir/test.knit', 0600)
1526
1475
        if not trans._can_roundtrip_unix_modebits():
1527
1476
            # Can't roundtrip, so no need to run this test
1528
1477
            return
1529
 
        knit = KnitVersionedFile('dir/test', trans, access_mode='w',
1530
 
                                 factory=None, create=True,
1531
 
                                 create_parent_dir=True,
1532
 
                                 delay_create=True,
1533
 
                                 file_mode=0660,
1534
 
                                 dir_mode=0770)
 
1478
        knit = make_file_knit('dir/test', trans, access_mode='w', factory=None,
 
1479
            create=True, create_parent_dir=True, delay_create=True,
 
1480
            file_mode=0660, dir_mode=0770)
1535
1481
        knit.add_lines('revid', [], ['a\n'])
1536
1482
        self.assertTransportMode(trans, 'dir', 0770)
1537
1483
        self.assertTransportMode(trans, 'dir/test.knit', 0660)
1542
1488
        if not trans._can_roundtrip_unix_modebits():
1543
1489
            # Can't roundtrip, so no need to run this test
1544
1490
            return
1545
 
        knit = KnitVersionedFile('dir/test', trans, access_mode='w',
1546
 
                                 factory=None, create=True,
1547
 
                                 create_parent_dir=True,
1548
 
                                 delay_create=True,
1549
 
                                 file_mode=0666,
1550
 
                                 dir_mode=0777)
 
1491
        knit = make_file_knit('dir/test', trans, access_mode='w', factory=None,
 
1492
            create=True, create_parent_dir=True, delay_create=True,
 
1493
            file_mode=0666, dir_mode=0777)
1551
1494
        knit.add_lines('revid', [], ['a\n'])
1552
1495
        self.assertTransportMode(trans, 'dir', 0777)
1553
1496
        self.assertTransportMode(trans, 'dir/test.knit', 0666)
2087
2030
    def test_weave_to_knit_matches(self):
2088
2031
        # check that the WeaveToKnit is_compatible function
2089
2032
        # registers True for a Weave to a Knit.
2090
 
        w = Weave()
 
2033
        w = Weave(get_scope=lambda:None)
2091
2034
        k = self.make_test_knit()
2092
2035
        self.failUnless(WeaveToKnit.is_compatible(w, k))
2093
2036
        self.failIf(WeaveToKnit.is_compatible(k, w))
2095
2038
        self.failIf(WeaveToKnit.is_compatible(k, k))
2096
2039
 
2097
2040
 
2098
 
class TestKnitCaching(KnitTests):
2099
 
    
2100
 
    def create_knit(self):
2101
 
        k = self.make_test_knit(True)
2102
 
        k.add_lines('text-1', [], split_lines(TEXT_1))
2103
 
        k.add_lines('text-2', [], split_lines(TEXT_2))
2104
 
        return k
2105
 
 
2106
 
    def test_no_caching(self):
2107
 
        k = self.create_knit()
2108
 
        # Nothing should be cached without setting 'enable_cache'
2109
 
        self.assertEqual({}, k._data._cache)
2110
 
 
2111
 
    def test_cache_data_read_raw(self):
2112
 
        k = self.create_knit()
2113
 
 
2114
 
        # Now cache and read
2115
 
        k.enable_cache()
2116
 
 
2117
 
        def read_one_raw(version):
2118
 
            pos_map = k._get_components_positions([version])
2119
 
            method, index_memo, next = pos_map[version]
2120
 
            lst = list(k._data.read_records_iter_raw([(version, index_memo)]))
2121
 
            self.assertEqual(1, len(lst))
2122
 
            return lst[0]
2123
 
 
2124
 
        val = read_one_raw('text-1')
2125
 
        self.assertEqual({'text-1':val[1]}, k._data._cache)
2126
 
 
2127
 
        k.clear_cache()
2128
 
        # After clear, new reads are not cached
2129
 
        self.assertEqual({}, k._data._cache)
2130
 
 
2131
 
        val2 = read_one_raw('text-1')
2132
 
        self.assertEqual(val, val2)
2133
 
        self.assertEqual({}, k._data._cache)
2134
 
 
2135
 
    def test_cache_data_read(self):
2136
 
        k = self.create_knit()
2137
 
 
2138
 
        def read_one(version):
2139
 
            pos_map = k._get_components_positions([version])
2140
 
            method, index_memo, next = pos_map[version]
2141
 
            lst = list(k._data.read_records_iter([(version, index_memo)]))
2142
 
            self.assertEqual(1, len(lst))
2143
 
            return lst[0]
2144
 
 
2145
 
        # Now cache and read
2146
 
        k.enable_cache()
2147
 
 
2148
 
        val = read_one('text-2')
2149
 
        self.assertEqual(['text-2'], k._data._cache.keys())
2150
 
        self.assertEqual('text-2', val[0])
2151
 
        content, digest = k._data._parse_record('text-2',
2152
 
                                                k._data._cache['text-2'])
2153
 
        self.assertEqual(content, val[1])
2154
 
        self.assertEqual(digest, val[2])
2155
 
 
2156
 
        k.clear_cache()
2157
 
        self.assertEqual({}, k._data._cache)
2158
 
 
2159
 
        val2 = read_one('text-2')
2160
 
        self.assertEqual(val, val2)
2161
 
        self.assertEqual({}, k._data._cache)
2162
 
 
2163
 
    def test_cache_read(self):
2164
 
        k = self.create_knit()
2165
 
        k.enable_cache()
2166
 
 
2167
 
        text = k.get_text('text-1')
2168
 
        self.assertEqual(TEXT_1, text)
2169
 
        self.assertEqual(['text-1'], k._data._cache.keys())
2170
 
 
2171
 
        k.clear_cache()
2172
 
        self.assertEqual({}, k._data._cache)
2173
 
 
2174
 
        text = k.get_text('text-1')
2175
 
        self.assertEqual(TEXT_1, text)
2176
 
        self.assertEqual({}, k._data._cache)
2177
 
 
2178
 
 
2179
2041
class TestKnitIndex(KnitTests):
2180
2042
 
2181
2043
    def test_add_versions_dictionary_compresses(self):
2516
2378
             ('tip', 'no-eol,line-delta', (None, 0, 100), ['parent'])])
2517
2379
        self.assertEqual([], self.caught_entries)
2518
2380
 
2519
 
    def test_iter_parents(self):
2520
 
        index1 = self.make_g_index('1', 1, [
2521
 
        # no parents
2522
 
            (('r0', ), 'N0 100', ([], )),
2523
 
        # 1 parent
2524
 
            (('r1', ), '', ([('r0', )], ))])
2525
 
        index2 = self.make_g_index('2', 1, [
2526
 
        # 2 parents
2527
 
            (('r2', ), 'N0 100', ([('r1', ), ('r0', )], )),
2528
 
            ])
2529
 
        combined_index = CombinedGraphIndex([index1, index2])
2530
 
        index = KnitGraphIndex(combined_index)
2531
 
        # XXX TODO a ghost
2532
 
        # cases: each sample data individually:
2533
 
        self.assertEqual(set([('r0', ())]),
2534
 
            set(index.iter_parents(['r0'])))
2535
 
        self.assertEqual(set([('r1', ('r0', ))]),
2536
 
            set(index.iter_parents(['r1'])))
2537
 
        self.assertEqual(set([('r2', ('r1', 'r0'))]),
2538
 
            set(index.iter_parents(['r2'])))
2539
 
        # no nodes returned for a missing node
2540
 
        self.assertEqual(set(),
2541
 
            set(index.iter_parents(['missing'])))
2542
 
        # 1 node returned with missing nodes skipped
2543
 
        self.assertEqual(set([('r1', ('r0', ))]),
2544
 
            set(index.iter_parents(['ghost1', 'r1', 'ghost'])))
2545
 
        # 2 nodes returned
2546
 
        self.assertEqual(set([('r0', ()), ('r1', ('r0', ))]),
2547
 
            set(index.iter_parents(['r0', 'r1'])))
2548
 
        # 2 nodes returned, missing skipped
2549
 
        self.assertEqual(set([('r0', ()), ('r1', ('r0', ))]),
2550
 
            set(index.iter_parents(['a', 'r0', 'b', 'r1', 'c'])))
2551
 
 
2552
 
 
2553
2381
class TestNoParentsGraphIndexKnit(KnitTests):
2554
2382
    """Tests for knits using KnitGraphIndex with no parents."""
2555
2383
 
2767
2595
             ('tip', 'no-eol,line-delta', (None, 0, 100), [])])
2768
2596
        self.assertEqual([], self.caught_entries)
2769
2597
 
2770
 
    def test_iter_parents(self):
2771
 
        index = self.two_graph_index()
2772
 
        self.assertEqual(set([
2773
 
            ('tip', ()), ('tail', ()), ('parent', ()), ('separate', ())
2774
 
            ]),
2775
 
            set(index.iter_parents(['tip', 'tail', 'ghost', 'parent', 'separate'])))
2776
 
        self.assertEqual(set([('tip', ())]),
2777
 
            set(index.iter_parents(['tip'])))
2778
 
        self.assertEqual(set(),
2779
 
            set(index.iter_parents([])))
2780
 
 
2781
 
 
2782
2598
class TestPackKnits(KnitTests):
2783
2599
    """Tests that use a _PackAccess and KnitGraphIndex."""
2784
2600
 
2833
2649
            set(result),
2834
2650
            set(index.get_ancestry(ancestry_versions, False)))
2835
2651
 
2836
 
    def assertIterParents(self, knit, versions, parent_versions, result):
2837
 
        """Check the result of an iter_parents call on knit."""
2838
 
        index = self.get_index(knit, knit.get_data_stream(versions))
2839
 
        self.assertEqual(result, index.iter_parents(parent_versions))
2840
 
 
2841
2652
    def assertGetMethod(self, knit, versions, version, result):
2842
2653
        index = self.get_index(knit, knit.get_data_stream(versions))
2843
2654
        self.assertEqual(result, index.get_method(version))
2908
2719
        # we thunk across.
2909
2720
        self.assertGetMethod(knit, ['c'], 'b', 'fulltext')
2910
2721
 
2911
 
    def test_iter_parents(self):
2912
 
        knit = self.make_knit_with_4_versions_2_dags()
2913
 
        self.assertIterParents(knit, ['a'], ['a'], [('a', ())])
2914
 
        self.assertIterParents(knit, ['a', 'b'], ['a', 'b'],
2915
 
            [('a', ()), ('b', ())])
2916
 
        self.assertIterParents(knit, ['a', 'b', 'c'], ['a', 'b', 'c'],
2917
 
            [('a', ()), ('b', ()), ('c', ('b', 'a'))])
2918
 
        self.assertIterParents(knit, ['a', 'b', 'c', 'd'],
2919
 
            ['a', 'b', 'c', 'd'],
2920
 
            [('a', ()), ('b', ()), ('c', ('b', 'a')), ('d', ('e', 'f'))])
2921
 
        self.assertIterParents(knit, ['c'], ['a', 'b', 'c'],
2922
 
            [('c', ('b', 'a'))])
2923
 
 
2924
2722
    def test_get_options(self):
2925
2723
        knit = self.make_knit_with_4_versions_2_dags()
2926
2724
        self.assertGetOptions(knit, 'a', ['no-eol', 'fulltext'])
3012
2810
            knit.get_data_stream([]))
3013
2811
        self.assertRaises(errors.KnitCorrupt,
3014
2812
            list, access.get_raw_records([(True, "A", None, None)]))
 
2813
 
 
2814
 
 
2815
class TestFormatSignatures(KnitTests):
 
2816
 
 
2817
    def test_knit_format_signatures(self):
 
2818
        """Different formats of knit have different signature strings."""
 
2819
        knit = self.make_test_knit(name='a', annotate=True)
 
2820
        self.assertEqual('knit-annotated', knit.get_format_signature())
 
2821
        knit = self.make_test_knit(name='p', annotate=False)
 
2822
        self.assertEqual('knit-plain', knit.get_format_signature())