/breezy/unstable

To get this branch, use:
bzr branch https://code.breezy-vcs.org/breezy/unstable

« back to all changes in this revision

Viewing changes to breezy/tests/test_knit.py

  • Committer: Jelmer Vernooij
  • Date: 2017-05-24 01:39:33 UTC
  • mfrom: (3815.3776.6)
  • Revision ID: jelmer@jelmer.uk-20170524013933-ir4y4tqtrsiz2ka2
New upstream snapshot.

Show diffs side-by-side

added added

removed removed

Lines of Context:
16
16
 
17
17
"""Tests for Knit data structure"""
18
18
 
19
 
from cStringIO import StringIO
20
19
import gzip
21
20
import sys
22
21
 
23
 
from bzrlib import (
 
22
from .. import (
24
23
    errors,
25
24
    knit,
26
25
    multiparent,
29
28
    tests,
30
29
    transport,
31
30
    )
32
 
from bzrlib.errors import (
 
31
from ..errors import (
33
32
    KnitHeaderError,
34
33
    NoSuchFile,
35
34
    )
36
 
from bzrlib.index import *
37
 
from bzrlib.knit import (
 
35
from ..index import *
 
36
from ..knit import (
38
37
    AnnotatedKnitContent,
39
38
    KnitContent,
40
39
    KnitVersionedFiles,
45
44
    _KnitKeyAccess,
46
45
    make_file_factory,
47
46
    )
48
 
from bzrlib.patiencediff import PatienceSequenceMatcher
49
 
from bzrlib.repofmt import (
 
47
from ..patiencediff import PatienceSequenceMatcher
 
48
from ..repofmt import (
50
49
    knitpack_repo,
51
50
    pack_repo,
52
51
    )
53
 
from bzrlib.tests import (
 
52
from ..sixish import (
 
53
    BytesIO,
 
54
    )
 
55
from . import (
54
56
    TestCase,
55
57
    TestCaseWithMemoryTransport,
56
58
    TestCaseWithTransport,
57
59
    TestNotApplicable,
58
60
    )
59
 
from bzrlib.versionedfile import (
 
61
from ..versionedfile import (
60
62
    AbsentContentFactory,
61
63
    ConstantMapper,
62
64
    network_bytes_to_kind_and_offset,
63
65
    RecordingVersionedFilesDecorator,
64
66
    )
65
 
from bzrlib.tests import (
 
67
from . import (
66
68
    features,
67
69
    )
68
70
 
69
71
 
70
72
compiled_knit_feature = features.ModuleAvailableFeature(
71
 
    'bzrlib._knit_load_data_pyx')
 
73
    'breezy._knit_load_data_pyx')
72
74
 
73
75
 
74
76
class KnitContentTestsMixin(object):
246
248
        if self.file_lines is None:
247
249
            raise NoSuchFile(filename)
248
250
        else:
249
 
            return StringIO("\n".join(self.file_lines))
 
251
            return BytesIO(b"\n".join(self.file_lines))
250
252
 
251
253
    def readv(self, relpath, offsets):
252
254
        fp = self.get(relpath)
444
446
        # populated
445
447
        try:
446
448
            raise _TestException('foobar')
447
 
        except _TestException, e:
 
449
        except _TestException as e:
448
450
            retry_exc = errors.RetryWithNewPacks(None, reload_occurred=False,
449
451
                                                 exc_info=sys.exc_info())
450
452
        # GZ 2010-08-10: Cycle with exc_info affects 3 tests
728
730
class LowLevelKnitDataTests(TestCase):
729
731
 
730
732
    def create_gz_content(self, text):
731
 
        sio = StringIO()
 
733
        sio = BytesIO()
732
734
        gz_file = gzip.GzipFile(mode='wb', fileobj=sio)
733
735
        gz_file.write(text)
734
736
        gz_file.close()
891
893
 
892
894
    def get_knit_index(self, transport, name, mode):
893
895
        mapper = ConstantMapper(name)
894
 
        from bzrlib._knit_load_data_py import _load_data_py
 
896
        from breezy._knit_load_data_py import _load_data_py
895
897
        self.overrideAttr(knit, '_load_data', _load_data_py)
896
898
        allow_writes = lambda: 'w' in mode
897
899
        return _KndxIndex(transport, mapper, lambda:None, allow_writes, lambda:True)
901
903
        index = self.get_knit_index(transport, "filename", "w")
902
904
        index.keys()
903
905
        call = transport.calls.pop(0)
904
 
        # call[1][1] is a StringIO - we can't test it by simple equality.
 
906
        # call[1][1] is a BytesIO - we can't test it by simple equality.
905
907
        self.assertEqual('put_file_non_atomic', call[0])
906
908
        self.assertEqual('filename.kndx', call[1][0])
907
909
        # With no history, _KndxIndex writes a new index:
943
945
            ])
944
946
        index = self.get_knit_index(transport, "filename", "r")
945
947
        self.assertEqual(1, len(index.keys()))
946
 
        self.assertEqual(set([("version",)]), index.keys())
 
948
        self.assertEqual({("version",)}, index.keys())
947
949
 
948
950
    def test_read_corrupted_header(self):
949
951
        transport = MockTransport(['not a bzr knit index header\n'])
989
991
        index.add_records([
990
992
            ((utf8_revision_id,), ["option"], ((utf8_revision_id,), 0, 1), [])])
991
993
        call = transport.calls.pop(0)
992
 
        # call[1][1] is a StringIO - we can't test it by simple equality.
 
994
        # call[1][1] is a BytesIO - we can't test it by simple equality.
993
995
        self.assertEqual('put_file_non_atomic', call[0])
994
996
        self.assertEqual('filename.kndx', call[1][0])
995
997
        # With no history, _KndxIndex writes a new index:
1008
1010
        index.add_records([
1009
1011
            (("version",), ["option"], (("version",), 0, 1), [(utf8_revision_id,)])])
1010
1012
        call = transport.calls.pop(0)
1011
 
        # call[1][1] is a StringIO - we can't test it by simple equality.
 
1013
        # call[1][1] is a BytesIO - we can't test it by simple equality.
1012
1014
        self.assertEqual('put_file_non_atomic', call[0])
1013
1015
        self.assertEqual('filename.kndx', call[1][0])
1014
1016
        # With no history, _KndxIndex writes a new index:
1026
1028
        self.assertEqual(set(), index.keys())
1027
1029
 
1028
1030
        index.add_records([(("a",), ["option"], (("a",), 0, 1), [])])
1029
 
        self.assertEqual(set([("a",)]), index.keys())
 
1031
        self.assertEqual({("a",)}, index.keys())
1030
1032
 
1031
1033
        index.add_records([(("a",), ["option"], (("a",), 0, 1), [])])
1032
 
        self.assertEqual(set([("a",)]), index.keys())
 
1034
        self.assertEqual({("a",)}, index.keys())
1033
1035
 
1034
1036
        index.add_records([(("b",), ["option"], (("b",), 0, 1), [])])
1035
 
        self.assertEqual(set([("a",), ("b",)]), index.keys())
 
1037
        self.assertEqual({("a",), ("b",)}, index.keys())
1036
1038
 
1037
1039
    def add_a_b(self, index, random_id=None):
1038
1040
        kwargs = {}
1062
1064
 
1063
1065
        self.add_a_b(index)
1064
1066
        call = transport.calls.pop(0)
1065
 
        # call[1][1] is a StringIO - we can't test it by simple equality.
 
1067
        # call[1][1] is a BytesIO - we can't test it by simple equality.
1066
1068
        self.assertEqual('put_file_non_atomic', call[0])
1067
1069
        self.assertEqual('filename.kndx', call[1][0])
1068
1070
        # With no history, _KndxIndex writes a new index:
1102
1104
        self.assertEqual(_KndxIndex.HEADER, call[1][1].getvalue())
1103
1105
        self.assertEqual({'create_parent_dir': True}, call[2])
1104
1106
        call = transport.calls.pop(0)
1105
 
        # call[1][1] is a StringIO - we can't test it by simple equality.
 
1107
        # call[1][1] is a BytesIO - we can't test it by simple equality.
1106
1108
        self.assertEqual('put_file_non_atomic', call[0])
1107
1109
        self.assertEqual('filename.kndx', call[1][0])
1108
1110
        # With no history, _KndxIndex writes a new index:
1194
1196
        index = self.get_knit_index(transport, 'filename', 'r')
1195
1197
        try:
1196
1198
            self.assertRaises(errors.KnitCorrupt, index.keys)
1197
 
        except TypeError, e:
 
1199
        except TypeError as e:
1198
1200
            if (str(e) == ('exceptions must be strings, classes, or instances,'
1199
1201
                           ' not exceptions.IndexError')):
1200
1202
                self.knownFailure('Pyrex <0.9.5 fails with TypeError when'
1213
1215
        index = self.get_knit_index(transport, 'filename', 'r')
1214
1216
        try:
1215
1217
            self.assertRaises(errors.KnitCorrupt, index.keys)
1216
 
        except TypeError, e:
 
1218
        except TypeError as e:
1217
1219
            if (str(e) == ('exceptions must be strings, classes, or instances,'
1218
1220
                           ' not exceptions.ValueError')):
1219
1221
                self.knownFailure('Pyrex <0.9.5 fails with TypeError when'
1232
1234
        index = self.get_knit_index(transport, 'filename', 'r')
1233
1235
        try:
1234
1236
            self.assertRaises(errors.KnitCorrupt, index.keys)
1235
 
        except TypeError, e:
 
1237
        except TypeError as e:
1236
1238
            if (str(e) == ('exceptions must be strings, classes, or instances,'
1237
1239
                           ' not exceptions.ValueError')):
1238
1240
                self.knownFailure('Pyrex <0.9.5 fails with TypeError when'
1249
1251
        index = self.get_knit_index(transport, 'filename', 'r')
1250
1252
        try:
1251
1253
            self.assertRaises(errors.KnitCorrupt, index.keys)
1252
 
        except TypeError, e:
 
1254
        except TypeError as e:
1253
1255
            if (str(e) == ('exceptions must be strings, classes, or instances,'
1254
1256
                           ' not exceptions.ValueError')):
1255
1257
                self.knownFailure('Pyrex <0.9.5 fails with TypeError when'
1266
1268
        index = self.get_knit_index(transport, 'filename', 'r')
1267
1269
        try:
1268
1270
            self.assertRaises(errors.KnitCorrupt, index.keys)
1269
 
        except TypeError, e:
 
1271
        except TypeError as e:
1270
1272
            if (str(e) == ('exceptions must be strings, classes, or instances,'
1271
1273
                           ' not exceptions.ValueError')):
1272
1274
                self.knownFailure('Pyrex <0.9.5 fails with TypeError when'
1291
1293
            "b option 10 10 0", # This line isn't terminated, ignored
1292
1294
            ])
1293
1295
        index = self.get_knit_index(transport, "filename", "r")
1294
 
        self.assertEqual(set([('a',)]), index.keys())
 
1296
        self.assertEqual({('a',)}, index.keys())
1295
1297
 
1296
1298
    def test_skip_incomplete_record(self):
1297
1299
        # A line with bogus data should just be skipped
1302
1304
            "c option 20 10 0 :", # Properly terminated, and starts with '\n'
1303
1305
            ])
1304
1306
        index = self.get_knit_index(transport, "filename", "r")
1305
 
        self.assertEqual(set([('a',), ('c',)]), index.keys())
 
1307
        self.assertEqual({('a',), ('c',)}, index.keys())
1306
1308
 
1307
1309
    def test_trailing_characters(self):
1308
1310
        # A line with bogus data should just be skipped
1313
1315
            "c option 20 10 0 :", # Properly terminated, and starts with '\n'
1314
1316
            ])
1315
1317
        index = self.get_knit_index(transport, "filename", "r")
1316
 
        self.assertEqual(set([('a',), ('c',)]), index.keys())
 
1318
        self.assertEqual({('a',), ('c',)}, index.keys())
1317
1319
 
1318
1320
 
1319
1321
class LowLevelKnitIndexTests_c(LowLevelKnitIndexTests):
1322
1324
 
1323
1325
    def get_knit_index(self, transport, name, mode):
1324
1326
        mapper = ConstantMapper(name)
1325
 
        from bzrlib._knit_load_data_pyx import _load_data_c
 
1327
        from breezy._knit_load_data_pyx import _load_data_c
1326
1328
        self.overrideAttr(knit, '_load_data', _load_data_c)
1327
1329
        allow_writes = lambda: mode == 'w'
1328
1330
        return _KndxIndex(transport, mapper, lambda:None,
1549
1551
            'a-2 fulltext 0 0 0 :\n'
1550
1552
            'a-3 fulltext 0 0 1 :'
1551
1553
            )
1552
 
        self.assertEqual(set([('a-3',), ('a-1',), ('a-2',)]), idx.keys())
 
1554
        self.assertEqual({('a-3',), ('a-1',), ('a-2',)}, idx.keys())
1553
1555
        self.assertEqual({
1554
1556
            ('a-1',): ((('a-1',), 0, 0), None, (), ('fulltext', False)),
1555
1557
            ('a-2',): ((('a-2',), 0, 0), None, (('a-1',),), ('fulltext', False)),
1587
1589
 
1588
1590
        # Assert the pre-condition
1589
1591
        def assertA1Only():
1590
 
            self.assertEqual(set([('a-1',)]), set(idx.keys()))
 
1592
            self.assertEqual({('a-1',)}, set(idx.keys()))
1591
1593
            self.assertEqual(
1592
1594
                {('a-1',): ((('a-1',), 0, 0), None, (), ('fulltext', False))},
1593
1595
                idx.get_build_details([('a-1',)]))
1662
1664
 
1663
1665
    def test_keys(self):
1664
1666
        index = self.two_graph_index()
1665
 
        self.assertEqual(set([('tail',), ('tip',), ('parent',), ('separate',)]),
 
1667
        self.assertEqual({('tail',), ('tip',), ('parent',), ('separate',)},
1666
1668
            set(index.keys()))
1667
1669
 
1668
1670
    def test_get_position(self):
1964
1966
 
1965
1967
    def test_keys(self):
1966
1968
        index = self.two_graph_index()
1967
 
        self.assertEqual(set([('tail',), ('tip',), ('parent',), ('separate',)]),
 
1969
        self.assertEqual({('tail',), ('tip',), ('parent',), ('separate',)},
1968
1970
            set(index.keys()))
1969
1971
 
1970
1972
    def test_get_position(self):
2128
2130
            }
2129
2131
        self.assertGroupKeysForIo([([f_a], set())],
2130
2132
                                  [f_a], [], positions)
2131
 
        self.assertGroupKeysForIo([([f_a], set([f_a]))],
 
2133
        self.assertGroupKeysForIo([([f_a], {f_a})],
2132
2134
                                  [f_a], [f_a], positions)
2133
2135
        self.assertGroupKeysForIo([([f_a, f_b], set([]))],
2134
2136
                                  [f_a, f_b], [], positions)
2135
 
        self.assertGroupKeysForIo([([f_a, f_b], set([f_b]))],
 
2137
        self.assertGroupKeysForIo([([f_a, f_b], {f_b})],
2136
2138
                                  [f_a, f_b], [f_b], positions)
2137
2139
        self.assertGroupKeysForIo([([f_a, f_b, g_a, g_b], set())],
2138
2140
                                  [f_a, g_a, f_b, g_b], [], positions)
2235
2237
        self.assertEqual([(key_basis, 'foo\n'), (key_basis, 'bar\n')], details)
2236
2238
        # Not optimised to date:
2237
2239
        # self.assertEqual([("annotate", key_basis)], basis.calls)
2238
 
        self.assertEqual([('get_parent_map', set([key_basis])),
2239
 
            ('get_parent_map', set([key_basis])),
 
2240
        self.assertEqual([('get_parent_map', {key_basis}),
 
2241
            ('get_parent_map', {key_basis}),
2240
2242
            ('get_record_stream', [key_basis], 'topological', True)],
2241
2243
            basis.calls)
2242
2244
 
2262
2264
        parent_map = test.get_parent_map([key, key_basis, key_missing])
2263
2265
        self.assertEqual({key: (),
2264
2266
            key_basis: ()}, parent_map)
2265
 
        self.assertEqual([("get_parent_map", set([key_basis, key_missing]))],
 
2267
        self.assertEqual([("get_parent_map", {key_basis, key_missing})],
2266
2268
            basis.calls)
2267
2269
 
2268
2270
    def test_get_record_stream_unordered_fulltexts(self):
2299
2301
        # It's not strictly minimal, but it seems reasonable for now for it to
2300
2302
        # ask which fallbacks have which parents.
2301
2303
        self.assertEqual([
2302
 
            ("get_parent_map", set([key_basis, key_missing])),
 
2304
            ("get_parent_map", {key_basis, key_missing}),
2303
2305
            ("get_record_stream", [key_basis], 'unordered', True)],
2304
2306
            calls)
2305
2307
 
2348
2350
        # It's not strictly minimal, but it seems reasonable for now for it to
2349
2351
        # ask which fallbacks have which parents.
2350
2352
        self.assertEqual([
2351
 
            ("get_parent_map", set([key_basis, key_basis_2, key_missing])),
 
2353
            ("get_parent_map", {key_basis, key_basis_2, key_missing}),
2352
2354
            # topological is requested from the fallback, because that is what
2353
2355
            # was requested at the top level.
2354
2356
            ("get_record_stream", [key_basis_2, key_basis], 'topological', True)],
2386
2388
        # It's not strictly minimal, but it seems reasonable for now for it to
2387
2389
        # ask which fallbacks have which parents.
2388
2390
        self.assertEqual([
2389
 
            ("get_parent_map", set([key_basis, key_missing])),
 
2391
            ("get_parent_map", {key_basis, key_missing}),
2390
2392
            ("get_record_stream", [key_basis], 'unordered', False)],
2391
2393
            calls)
2392
2394
 
2432
2434
        # It's not strictly minimal, but it seems reasonable for now for it to
2433
2435
        # ask which fallbacks have which parents.
2434
2436
        self.assertEqual([
2435
 
            ("get_parent_map", set([key_basis, key_basis_2, key_missing])),
 
2437
            ("get_parent_map", {key_basis, key_basis_2, key_missing}),
2436
2438
            ("get_record_stream", [key_basis_2, key_basis], 'topological', False)],
2437
2439
            calls)
2438
2440
 
2456
2458
        sha1s = test.get_sha1s([key, key_missing, key_basis])
2457
2459
        self.assertEqual({key: key_sha1sum,
2458
2460
            key_basis: basis_sha1sum}, sha1s)
2459
 
        self.assertEqual([("get_sha1s", set([key_basis, key_missing]))],
 
2461
        self.assertEqual([("get_sha1s", {key_basis, key_missing})],
2460
2462
            basis.calls)
2461
2463
 
2462
2464
    def test_insert_record_stream(self):
2475
2477
        test.insert_record_stream(stream)
2476
2478
        # XXX: this does somewhat too many calls in making sure of whether it
2477
2479
        # has to recreate the full text.
2478
 
        self.assertEqual([("get_parent_map", set([key_basis])),
2479
 
             ('get_parent_map', set([key_basis])),
 
2480
        self.assertEqual([("get_parent_map", {key_basis}),
 
2481
             ('get_parent_map', {key_basis}),
2480
2482
             ('get_record_stream', [key_basis], 'unordered', True)],
2481
2483
            basis.calls)
2482
2484
        self.assertEqual({key_delta:(key_basis,)},
2495
2497
        basis.calls = []
2496
2498
        lines = list(test.iter_lines_added_or_present_in_keys([key1]))
2497
2499
        self.assertEqual([("foo\n", key1)], lines)
2498
 
        self.assertEqual([("iter_lines_added_or_present_in_keys", set([key1]))],
 
2500
        self.assertEqual([("iter_lines_added_or_present_in_keys", {key1})],
2499
2501
            basis.calls)
2500
2502
        # keys in both are not duplicated:
2501
2503
        test.add_lines(key2, (), ["bar\n"])
2517
2519
        basis.add_lines(key1, (), [])
2518
2520
        basis.calls = []
2519
2521
        keys = test.keys()
2520
 
        self.assertEqual(set([key1]), set(keys))
 
2522
        self.assertEqual({key1}, set(keys))
2521
2523
        self.assertEqual([("keys",)], basis.calls)
2522
2524
        # keys in both are not duplicated:
2523
2525
        test.add_lines(key2, (), [])
2525
2527
        basis.calls = []
2526
2528
        keys = test.keys()
2527
2529
        self.assertEqual(2, len(keys))
2528
 
        self.assertEqual(set([key1, key2]), set(keys))
 
2530
        self.assertEqual({key1, key2}, set(keys))
2529
2531
        self.assertEqual([("keys",)], basis.calls)
2530
2532
 
2531
2533
    def test_add_mpdiffs(self):
2543
2545
        diffs = source.make_mpdiffs([key_delta])
2544
2546
        test.add_mpdiffs([(key_delta, (key_basis,),
2545
2547
            source.get_sha1s([key_delta])[key_delta], diffs[0])])
2546
 
        self.assertEqual([("get_parent_map", set([key_basis])),
 
2548
        self.assertEqual([("get_parent_map", {key_basis}),
2547
2549
            ('get_record_stream', [key_basis], 'unordered', True),],
2548
2550
            basis.calls)
2549
2551
        self.assertEqual({key_delta:(key_basis,)},
2571
2573
            diffs)
2572
2574
        self.assertEqual(3, len(basis.calls))
2573
2575
        self.assertEqual([
2574
 
            ("get_parent_map", set([key_left, key_right])),
2575
 
            ("get_parent_map", set([key_left, key_right])),
 
2576
            ("get_parent_map", {key_left, key_right}),
 
2577
            ("get_parent_map", {key_left, key_right}),
2576
2578
            ],
2577
2579
            basis.calls[:-1])
2578
2580
        last_call = basis.calls[-1]
2579
2581
        self.assertEqual('get_record_stream', last_call[0])
2580
 
        self.assertEqual(set([key_left, key_right]), set(last_call[1]))
 
2582
        self.assertEqual({key_left, key_right}, set(last_call[1]))
2581
2583
        self.assertEqual('topological', last_call[2])
2582
2584
        self.assertEqual(True, last_call[3])
2583
2585