/brz/remove-bazaar

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/brz/remove-bazaar
5590.1.1 by John Arbash Meinel
Stop using tuned_gzip, it seems to give incorrect results on python 2.7
1
# Copyright (C) 2006-2011 Canonical Ltd
1563.2.4 by Robert Collins
First cut at including the knit implementation of versioned_file.
2
#
3
# This program is free software; you can redistribute it and/or modify
4
# it under the terms of the GNU General Public License as published by
5
# the Free Software Foundation; either version 2 of the License, or
6
# (at your option) any later version.
7
#
8
# This program is distributed in the hope that it will be useful,
9
# but WITHOUT ANY WARRANTY; without even the implied warranty of
10
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11
# GNU General Public License for more details.
12
#
13
# You should have received a copy of the GNU General Public License
14
# along with this program; if not, write to the Free Software
4183.7.1 by Sabin Iacob
update FSF mailing address
15
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
1563.2.4 by Robert Collins
First cut at including the knit implementation of versioned_file.
16
17
"""Tests for Knit data structure"""
18
5590.1.1 by John Arbash Meinel
Stop using tuned_gzip, it seems to give incorrect results on python 2.7
19
import gzip
6985 by Jelmer Vernooij
Merge lp:~jelmer/brz/python3-weave-fmt.
20
from io import BytesIO
2484.1.17 by John Arbash Meinel
Workaround for Pyrex <0.9.5 and python >=2.5 incompatibilities.
21
import sys
1563.2.4 by Robert Collins
First cut at including the knit implementation of versioned_file.
22
6624 by Jelmer Vernooij
Merge Python3 porting work ('py3 pokes')
23
from .. import (
2196.2.5 by John Arbash Meinel
Add an exception class when the knit index storage method is unknown, and properly test for it
24
    errors,
3350.8.12 by Robert Collins
Stacked make_mpdiffs.
25
    multiparent,
3734.2.4 by Vincent Ladeuil
Fix python2.6 deprecation warnings related to hashlib.
26
    osutils,
4913.2.24 by John Arbash Meinel
Track down a few more import typos.
27
    tests,
5273.1.7 by Vincent Ladeuil
No more use of the get_transport imported *symbol*, all uses are through
28
    transport,
2196.2.5 by John Arbash Meinel
Add an exception class when the knit index storage method is unknown, and properly test for it
29
    )
6670.4.1 by Jelmer Vernooij
Update imports.
30
from ..bzr import (
31
    knit,
32
    pack,
33
    )
34
from ..bzr.index import *
35
from ..bzr.knit import (
2794.1.2 by Robert Collins
Nuke versioned file add/get delta support, allowing easy simplification of unannotated Content, reducing memory copies and friction during commit on unannotated texts.
36
    AnnotatedKnitContent,
2151.1.1 by John Arbash Meinel
(Dmitry Vasiliev) Tune KnitContent and add tests
37
    KnitContent,
6729.7.2 by Jelmer Vernooij
Finish move.
38
    KnitCorrupt,
39
    KnitDataStreamIncompatible,
40
    KnitDataStreamUnknown,
6729.7.1 by Jelmer Vernooij
Move some knit errors.
41
    KnitHeaderError,
6729.7.2 by Jelmer Vernooij
Finish move.
42
    KnitIndexUnknownMethod,
3350.6.4 by Robert Collins
First cut at pluralised VersionedFiles. Some rather massive API incompatabilities, primarily because of the difficulty of coherence among competing stores.
43
    KnitVersionedFiles,
2794.1.2 by Robert Collins
Nuke versioned file add/get delta support, allowing easy simplification of unannotated Content, reducing memory copies and friction during commit on unannotated texts.
44
    PlainKnitContent,
4005.3.6 by Robert Collins
Support delta_closure=True with NetworkRecordStream to transmit deltas over the wire when full text extraction is required on the far end.
45
    _VFContentMapGenerator,
3350.6.4 by Robert Collins
First cut at pluralised VersionedFiles. Some rather massive API incompatabilities, primarily because of the difficulty of coherence among competing stores.
46
    _KndxIndex,
47
    _KnitGraphIndex,
48
    _KnitKeyAccess,
49
    make_file_factory,
2158.3.1 by Dmitry Vasiliev
KnitIndex tests/fixes/optimizations
50
    )
6624 by Jelmer Vernooij
Merge Python3 porting work ('py3 pokes')
51
from ..patiencediff import PatienceSequenceMatcher
6670.4.5 by Jelmer Vernooij
Move breezy.repofmt contents to breezy.bzr.
52
from ..bzr import (
5757.8.11 by Jelmer Vernooij
Merge knitpackrepo-6.
53
    knitpack_repo,
54
    pack_repo,
55
    )
6624 by Jelmer Vernooij
Merge Python3 porting work ('py3 pokes')
56
from . import (
2592.3.66 by Robert Collins
Allow adaption of KnitData to pack files.
57
    TestCase,
58
    TestCaseWithMemoryTransport,
59
    TestCaseWithTransport,
3787.1.1 by Robert Collins
Embed the failed text in sha1 knit errors.
60
    TestNotApplicable,
2592.3.66 by Robert Collins
Allow adaption of KnitData to pack files.
61
    )
6670.4.1 by Jelmer Vernooij
Update imports.
62
from ..bzr.versionedfile import (
3350.8.6 by Robert Collins
get_record_stream stacking for delta access.
63
    AbsentContentFactory,
3350.8.2 by Robert Collins
stacked get_parent_map.
64
    ConstantMapper,
4005.3.6 by Robert Collins
Support delta_closure=True with NetworkRecordStream to transmit deltas over the wire when full text extraction is required on the far end.
65
    network_bytes_to_kind_and_offset,
3350.8.2 by Robert Collins
stacked get_parent_map.
66
    RecordingVersionedFilesDecorator,
67
    )
6624 by Jelmer Vernooij
Merge Python3 porting work ('py3 pokes')
68
from . import (
5967.12.1 by Martin Pool
Move all test features into bzrlib.tests.features
69
    features,
70
    )
71
72
73
compiled_knit_feature = features.ModuleAvailableFeature(
6670.4.1 by Jelmer Vernooij
Update imports.
74
    'breezy.bzr._knit_load_data_pyx')
2484.1.1 by John Arbash Meinel
Add an initial function to read knit indexes in pyrex.
75
76
6729.7.2 by Jelmer Vernooij
Finish move.
77
class ErrorTests(TestCase):
78
79
    def test_knit_data_stream_incompatible(self):
80
        error = KnitDataStreamIncompatible(
81
            'stream format', 'target format')
82
        self.assertEqual('Cannot insert knit data stream of format '
83
                         '"stream format" into knit of format '
84
                         '"target format".', str(error))
85
86
    def test_knit_data_stream_unknown(self):
87
        error = KnitDataStreamUnknown(
88
            'stream format')
89
        self.assertEqual('Cannot parse knit data stream of format '
90
                         '"stream format".', str(error))
91
92
    def test_knit_header_error(self):
93
        error = KnitHeaderError('line foo\n', 'path/to/file')
94
        self.assertEqual("Knit header error: 'line foo\\n' unexpected"
95
                         " for file \"path/to/file\".", str(error))
96
97
    def test_knit_index_unknown_method(self):
98
        error = KnitIndexUnknownMethod('http://host/foo.kndx',
99
                                       ['bad', 'no-eol'])
100
        self.assertEqual("Knit index http://host/foo.kndx does not have a"
101
                         " known method in options: ['bad', 'no-eol']",
102
                         str(error))
103
104
2794.1.2 by Robert Collins
Nuke versioned file add/get delta support, allowing easy simplification of unannotated Content, reducing memory copies and friction during commit on unannotated texts.
105
class KnitContentTestsMixin(object):
2151.1.1 by John Arbash Meinel
(Dmitry Vasiliev) Tune KnitContent and add tests
106
107
    def test_constructor(self):
2794.1.2 by Robert Collins
Nuke versioned file add/get delta support, allowing easy simplification of unannotated Content, reducing memory copies and friction during commit on unannotated texts.
108
        content = self._make_content([])
2151.1.1 by John Arbash Meinel
(Dmitry Vasiliev) Tune KnitContent and add tests
109
110
    def test_text(self):
2794.1.2 by Robert Collins
Nuke versioned file add/get delta support, allowing easy simplification of unannotated Content, reducing memory copies and friction during commit on unannotated texts.
111
        content = self._make_content([])
2151.1.1 by John Arbash Meinel
(Dmitry Vasiliev) Tune KnitContent and add tests
112
        self.assertEqual(content.text(), [])
113
7143.15.2 by Jelmer Vernooij
Run autopep8.
114
        content = self._make_content(
115
            [(b"origin1", b"text1"), (b"origin2", b"text2")])
6973.14.2 by Jelmer Vernooij
Fix some knit tests.
116
        self.assertEqual(content.text(), [b"text1", b"text2"])
2151.1.1 by John Arbash Meinel
(Dmitry Vasiliev) Tune KnitContent and add tests
117
2794.1.2 by Robert Collins
Nuke versioned file add/get delta support, allowing easy simplification of unannotated Content, reducing memory copies and friction during commit on unannotated texts.
118
    def test_copy(self):
7143.15.2 by Jelmer Vernooij
Run autopep8.
119
        content = self._make_content(
120
            [(b"origin1", b"text1"), (b"origin2", b"text2")])
2794.1.2 by Robert Collins
Nuke versioned file add/get delta support, allowing easy simplification of unannotated Content, reducing memory copies and friction during commit on unannotated texts.
121
        copy = content.copy()
122
        self.assertIsInstance(copy, content.__class__)
123
        self.assertEqual(copy.annotate(), content.annotate())
124
125
    def assertDerivedBlocksEqual(self, source, target, noeol=False):
126
        """Assert that the derived matching blocks match real output"""
127
        source_lines = source.splitlines(True)
128
        target_lines = target.splitlines(True)
7143.15.2 by Jelmer Vernooij
Run autopep8.
129
2794.1.2 by Robert Collins
Nuke versioned file add/get delta support, allowing easy simplification of unannotated Content, reducing memory copies and friction during commit on unannotated texts.
130
        def nl(line):
131
            if noeol and not line.endswith('\n'):
132
                return line + '\n'
133
            else:
134
                return line
7143.15.2 by Jelmer Vernooij
Run autopep8.
135
        source_content = self._make_content(
136
            [(None, nl(l)) for l in source_lines])
137
        target_content = self._make_content(
138
            [(None, nl(l)) for l in target_lines])
2794.1.2 by Robert Collins
Nuke versioned file add/get delta support, allowing easy simplification of unannotated Content, reducing memory copies and friction during commit on unannotated texts.
139
        line_delta = source_content.line_delta(target_content)
140
        delta_blocks = list(KnitContent.get_line_delta_blocks(line_delta,
7143.15.2 by Jelmer Vernooij
Run autopep8.
141
                                                              source_lines, target_lines))
5279.1.1 by Andrew Bennetts
lazy_import most things in merge.py; add a few representative modules to the import tariff tests; tweak a couple of other modules so that patiencediff is not necessarily imported; remove a bunch of unused imports from test_knit.py.
142
        matcher = PatienceSequenceMatcher(None, source_lines, target_lines)
143
        matcher_blocks = list(matcher.get_matching_blocks())
2794.1.2 by Robert Collins
Nuke versioned file add/get delta support, allowing easy simplification of unannotated Content, reducing memory copies and friction during commit on unannotated texts.
144
        self.assertEqual(matcher_blocks, delta_blocks)
145
146
    def test_get_line_delta_blocks(self):
147
        self.assertDerivedBlocksEqual('a\nb\nc\n', 'q\nc\n')
148
        self.assertDerivedBlocksEqual(TEXT_1, TEXT_1)
149
        self.assertDerivedBlocksEqual(TEXT_1, TEXT_1A)
150
        self.assertDerivedBlocksEqual(TEXT_1, TEXT_1B)
151
        self.assertDerivedBlocksEqual(TEXT_1B, TEXT_1A)
152
        self.assertDerivedBlocksEqual(TEXT_1A, TEXT_1B)
153
        self.assertDerivedBlocksEqual(TEXT_1A, '')
154
        self.assertDerivedBlocksEqual('', TEXT_1A)
155
        self.assertDerivedBlocksEqual('', '')
156
        self.assertDerivedBlocksEqual('a\nb\nc', 'a\nb\nc\nd')
157
158
    def test_get_line_delta_blocks_noeol(self):
159
        """Handle historical knit deltas safely
160
161
        Some existing knit deltas don't consider the last line to differ
162
        when the only difference whether it has a final newline.
163
164
        New knit deltas appear to always consider the last line to differ
165
        in this case.
166
        """
167
        self.assertDerivedBlocksEqual('a\nb\nc', 'a\nb\nc\nd\n', noeol=True)
168
        self.assertDerivedBlocksEqual('a\nb\nc\nd\n', 'a\nb\nc', noeol=True)
169
        self.assertDerivedBlocksEqual('a\nb\nc\n', 'a\nb\nc', noeol=True)
170
        self.assertDerivedBlocksEqual('a\nb\nc', 'a\nb\nc\n', noeol=True)
171
172
3350.6.4 by Robert Collins
First cut at pluralised VersionedFiles. Some rather massive API incompatabilities, primarily because of the difficulty of coherence among competing stores.
173
TEXT_1 = """\
174
Banana cup cakes:
175
176
- bananas
177
- eggs
178
- broken tea cups
179
"""
180
181
TEXT_1A = """\
182
Banana cup cake recipe
183
(serves 6)
184
185
- bananas
186
- eggs
187
- broken tea cups
188
- self-raising flour
189
"""
190
191
TEXT_1B = """\
192
Banana cup cake recipe
193
194
- bananas (do not use plantains!!!)
195
- broken tea cups
196
- flour
197
"""
198
199
delta_1_1a = """\
200
0,1,2
201
Banana cup cake recipe
202
(serves 6)
203
5,5,1
204
- self-raising flour
205
"""
206
207
TEXT_2 = """\
208
Boeuf bourguignon
209
210
- beef
211
- red wine
212
- small onions
213
- carrot
214
- mushrooms
215
"""
216
217
2794.1.2 by Robert Collins
Nuke versioned file add/get delta support, allowing easy simplification of unannotated Content, reducing memory copies and friction during commit on unannotated texts.
218
class TestPlainKnitContent(TestCase, KnitContentTestsMixin):
219
220
    def _make_content(self, lines):
221
        annotated_content = AnnotatedKnitContent(lines)
222
        return PlainKnitContent(annotated_content.text(), 'bogus')
223
224
    def test_annotate(self):
225
        content = self._make_content([])
226
        self.assertEqual(content.annotate(), [])
227
7143.15.2 by Jelmer Vernooij
Run autopep8.
228
        content = self._make_content(
229
            [("origin1", "text1"), ("origin2", "text2")])
2794.1.2 by Robert Collins
Nuke versioned file add/get delta support, allowing easy simplification of unannotated Content, reducing memory copies and friction during commit on unannotated texts.
230
        self.assertEqual(content.annotate(),
7143.15.2 by Jelmer Vernooij
Run autopep8.
231
                         [("bogus", "text1"), ("bogus", "text2")])
2794.1.2 by Robert Collins
Nuke versioned file add/get delta support, allowing easy simplification of unannotated Content, reducing memory copies and friction during commit on unannotated texts.
232
233
    def test_line_delta(self):
234
        content1 = self._make_content([("", "a"), ("", "b")])
235
        content2 = self._make_content([("", "a"), ("", "a"), ("", "c")])
236
        self.assertEqual(content1.line_delta(content2),
7143.15.2 by Jelmer Vernooij
Run autopep8.
237
                         [(1, 2, 2, ["a", "c"])])
2794.1.2 by Robert Collins
Nuke versioned file add/get delta support, allowing easy simplification of unannotated Content, reducing memory copies and friction during commit on unannotated texts.
238
239
    def test_line_delta_iter(self):
240
        content1 = self._make_content([("", "a"), ("", "b")])
241
        content2 = self._make_content([("", "a"), ("", "a"), ("", "c")])
242
        it = content1.line_delta_iter(content2)
6634.2.1 by Martin
Apply 2to3 next fixer and make compatible
243
        self.assertEqual(next(it), (1, 2, 2, ["a", "c"]))
244
        self.assertRaises(StopIteration, next, it)
2794.1.2 by Robert Collins
Nuke versioned file add/get delta support, allowing easy simplification of unannotated Content, reducing memory copies and friction during commit on unannotated texts.
245
246
247
class TestAnnotatedKnitContent(TestCase, KnitContentTestsMixin):
248
249
    def _make_content(self, lines):
250
        return AnnotatedKnitContent(lines)
251
252
    def test_annotate(self):
253
        content = self._make_content([])
254
        self.assertEqual(content.annotate(), [])
255
7143.15.2 by Jelmer Vernooij
Run autopep8.
256
        content = self._make_content(
257
            [(b"origin1", b"text1"), (b"origin2", b"text2")])
2151.1.1 by John Arbash Meinel
(Dmitry Vasiliev) Tune KnitContent and add tests
258
        self.assertEqual(content.annotate(),
7143.15.2 by Jelmer Vernooij
Run autopep8.
259
                         [(b"origin1", b"text1"), (b"origin2", b"text2")])
2151.1.1 by John Arbash Meinel
(Dmitry Vasiliev) Tune KnitContent and add tests
260
261
    def test_line_delta(self):
2794.1.2 by Robert Collins
Nuke versioned file add/get delta support, allowing easy simplification of unannotated Content, reducing memory copies and friction during commit on unannotated texts.
262
        content1 = self._make_content([("", "a"), ("", "b")])
263
        content2 = self._make_content([("", "a"), ("", "a"), ("", "c")])
2151.1.1 by John Arbash Meinel
(Dmitry Vasiliev) Tune KnitContent and add tests
264
        self.assertEqual(content1.line_delta(content2),
7143.15.2 by Jelmer Vernooij
Run autopep8.
265
                         [(1, 2, 2, [("", "a"), ("", "c")])])
2151.1.1 by John Arbash Meinel
(Dmitry Vasiliev) Tune KnitContent and add tests
266
267
    def test_line_delta_iter(self):
2794.1.2 by Robert Collins
Nuke versioned file add/get delta support, allowing easy simplification of unannotated Content, reducing memory copies and friction during commit on unannotated texts.
268
        content1 = self._make_content([("", "a"), ("", "b")])
269
        content2 = self._make_content([("", "a"), ("", "a"), ("", "c")])
2151.1.1 by John Arbash Meinel
(Dmitry Vasiliev) Tune KnitContent and add tests
270
        it = content1.line_delta_iter(content2)
6634.2.1 by Martin
Apply 2to3 next fixer and make compatible
271
        self.assertEqual(next(it), (1, 2, 2, [("", "a"), ("", "c")]))
272
        self.assertRaises(StopIteration, next, it)
2151.1.1 by John Arbash Meinel
(Dmitry Vasiliev) Tune KnitContent and add tests
273
2158.3.1 by Dmitry Vasiliev
KnitIndex tests/fixes/optimizations
274
275
class MockTransport(object):
276
277
    def __init__(self, file_lines=None):
278
        self.file_lines = file_lines
279
        self.calls = []
2196.2.3 by John Arbash Meinel
Update tests and code to pass after merging bzr.dev
280
        # We have no base directory for the MockTransport
281
        self.base = ''
2158.3.1 by Dmitry Vasiliev
KnitIndex tests/fixes/optimizations
282
283
    def get(self, filename):
284
        if self.file_lines is None:
6729.7.2 by Jelmer Vernooij
Finish move.
285
            raise errors.NoSuchFile(filename)
2158.3.1 by Dmitry Vasiliev
KnitIndex tests/fixes/optimizations
286
        else:
6621.22.2 by Martin
Use BytesIO or StringIO from bzrlib.sixish
287
            return BytesIO(b"\n".join(self.file_lines))
2158.3.1 by Dmitry Vasiliev
KnitIndex tests/fixes/optimizations
288
2329.1.1 by John Arbash Meinel
Update _KnitData parser to raise more helpful errors when it detects corruption.
289
    def readv(self, relpath, offsets):
290
        fp = self.get(relpath)
291
        for offset, size in offsets:
292
            fp.seek(offset)
293
            yield offset, fp.read(size)
294
2158.3.1 by Dmitry Vasiliev
KnitIndex tests/fixes/optimizations
295
    def __getattr__(self, name):
296
        def queue_call(*args, **kwargs):
297
            self.calls.append((name, args, kwargs))
298
        return queue_call
299
300
3789.2.2 by John Arbash Meinel
Test that a readv() failing after yielding data will still raise Retry
301
class MockReadvFailingTransport(MockTransport):
302
    """Fail in the middle of a readv() result.
303
3789.2.3 by John Arbash Meinel
Change the mocking a bit, so we can be sure it is failing at the right time.
304
    This Transport will successfully yield the first two requested hunks, but
305
    raise NoSuchFile for the rest.
3789.2.2 by John Arbash Meinel
Test that a readv() failing after yielding data will still raise Retry
306
    """
307
308
    def readv(self, relpath, offsets):
3789.2.3 by John Arbash Meinel
Change the mocking a bit, so we can be sure it is failing at the right time.
309
        count = 0
3789.2.2 by John Arbash Meinel
Test that a readv() failing after yielding data will still raise Retry
310
        for result in MockTransport.readv(self, relpath, offsets):
3789.2.3 by John Arbash Meinel
Change the mocking a bit, so we can be sure it is failing at the right time.
311
            count += 1
312
            # we use 2 because the first offset is the pack header, the second
313
            # is the first actual content requset
314
            if count > 2:
3789.2.2 by John Arbash Meinel
Test that a readv() failing after yielding data will still raise Retry
315
                raise errors.NoSuchFile(relpath)
316
            yield result
317
318
2592.3.66 by Robert Collins
Allow adaption of KnitData to pack files.
319
class KnitRecordAccessTestsMixin(object):
320
    """Tests for getting and putting knit records."""
321
322
    def test_add_raw_records(self):
323
        """Add_raw_records adds records retrievable later."""
324
        access = self.get_access()
6985 by Jelmer Vernooij
Merge lp:~jelmer/brz/python3-weave-fmt.
325
        memos = access.add_raw_records([(b'key', 10)], b'1234567890')
326
        self.assertEqual([b'1234567890'], list(access.get_raw_records(memos)))
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
327
2592.3.67 by Robert Collins
More tests for bzrlib.knit._PackAccess.
328
    def test_add_several_raw_records(self):
329
        """add_raw_records with many records and read some back."""
330
        access = self.get_access()
6985 by Jelmer Vernooij
Merge lp:~jelmer/brz/python3-weave-fmt.
331
        memos = access.add_raw_records([(b'key', 10), (b'key2', 2), (b'key3', 5)],
7143.15.2 by Jelmer Vernooij
Run autopep8.
332
                                       b'12345678901234567')
6985 by Jelmer Vernooij
Merge lp:~jelmer/brz/python3-weave-fmt.
333
        self.assertEqual([b'1234567890', b'12', b'34567'],
7143.15.2 by Jelmer Vernooij
Run autopep8.
334
                         list(access.get_raw_records(memos)))
6985 by Jelmer Vernooij
Merge lp:~jelmer/brz/python3-weave-fmt.
335
        self.assertEqual([b'1234567890'],
7143.15.2 by Jelmer Vernooij
Run autopep8.
336
                         list(access.get_raw_records(memos[0:1])))
6985 by Jelmer Vernooij
Merge lp:~jelmer/brz/python3-weave-fmt.
337
        self.assertEqual([b'12'],
7143.15.2 by Jelmer Vernooij
Run autopep8.
338
                         list(access.get_raw_records(memos[1:2])))
6985 by Jelmer Vernooij
Merge lp:~jelmer/brz/python3-weave-fmt.
339
        self.assertEqual([b'34567'],
7143.15.2 by Jelmer Vernooij
Run autopep8.
340
                         list(access.get_raw_records(memos[2:3])))
6985 by Jelmer Vernooij
Merge lp:~jelmer/brz/python3-weave-fmt.
341
        self.assertEqual([b'1234567890', b'34567'],
7143.15.2 by Jelmer Vernooij
Run autopep8.
342
                         list(access.get_raw_records(memos[0:1] + memos[2:3])))
2592.3.67 by Robert Collins
More tests for bzrlib.knit._PackAccess.
343
2592.3.66 by Robert Collins
Allow adaption of KnitData to pack files.
344
345
class TestKnitKnitAccess(TestCaseWithMemoryTransport, KnitRecordAccessTestsMixin):
346
    """Tests for the .kndx implementation."""
347
348
    def get_access(self):
349
        """Get a .knit style access instance."""
3350.6.4 by Robert Collins
First cut at pluralised VersionedFiles. Some rather massive API incompatabilities, primarily because of the difficulty of coherence among competing stores.
350
        mapper = ConstantMapper("foo")
351
        access = _KnitKeyAccess(self.get_transport(), mapper)
2592.3.66 by Robert Collins
Allow adaption of KnitData to pack files.
352
        return access
3789.2.6 by John Arbash Meinel
Make _DirectPackAccess.reload_or_raise maintain the logic.
353
354
355
class _TestException(Exception):
356
    """Just an exception for local tests to use."""
357
2592.3.66 by Robert Collins
Allow adaption of KnitData to pack files.
358
359
class TestPackKnitAccess(TestCaseWithMemoryTransport, KnitRecordAccessTestsMixin):
360
    """Tests for the pack based access."""
361
362
    def get_access(self):
2592.3.67 by Robert Collins
More tests for bzrlib.knit._PackAccess.
363
        return self._get_access()[0]
364
365
    def _get_access(self, packname='packfile', index='FOO'):
2592.3.66 by Robert Collins
Allow adaption of KnitData to pack files.
366
        transport = self.get_transport()
7143.15.2 by Jelmer Vernooij
Run autopep8.
367
2592.3.66 by Robert Collins
Allow adaption of KnitData to pack files.
368
        def write_data(bytes):
2592.3.67 by Robert Collins
More tests for bzrlib.knit._PackAccess.
369
            transport.append_bytes(packname, bytes)
2592.3.66 by Robert Collins
Allow adaption of KnitData to pack files.
370
        writer = pack.ContainerWriter(write_data)
371
        writer.begin()
5757.5.1 by Jelmer Vernooij
Move _DirectPackAccess to bzrlib.repofmt.pack_repo.
372
        access = pack_repo._DirectPackAccess({})
3350.6.4 by Robert Collins
First cut at pluralised VersionedFiles. Some rather massive API incompatabilities, primarily because of the difficulty of coherence among competing stores.
373
        access.set_writer(writer, index, (transport, packname))
2592.3.67 by Robert Collins
More tests for bzrlib.knit._PackAccess.
374
        return access, writer
2592.3.66 by Robert Collins
Allow adaption of KnitData to pack files.
375
3789.2.5 by John Arbash Meinel
Change _DirectPackAccess to only raise Retry when _reload_func is defined.
376
    def make_pack_file(self):
377
        """Create a pack file with 2 records."""
378
        access, writer = self._get_access(packname='packname', index='foo')
379
        memos = []
6985 by Jelmer Vernooij
Merge lp:~jelmer/brz/python3-weave-fmt.
380
        memos.extend(access.add_raw_records([(b'key1', 10)], b'1234567890'))
381
        memos.extend(access.add_raw_records([(b'key2', 5)], b'12345'))
3789.2.5 by John Arbash Meinel
Change _DirectPackAccess to only raise Retry when _reload_func is defined.
382
        writer.end()
383
        return memos
384
5050.64.1 by Andrew Bennetts
Add reload-and-retry logic to RepositoryPackCollection.pack when a concurrent pack happens.
385
    def test_pack_collection_pack_retries(self):
386
        """An explicit pack of a pack collection succeeds even when a
387
        concurrent pack happens.
388
        """
389
        builder = self.make_branch_builder('.')
390
        builder.start_series()
6816.2.1 by Jelmer Vernooij
Migrate some build_snapshot code over to having revision_id as keyword argument.
391
        builder.build_snapshot(None, [
6985 by Jelmer Vernooij
Merge lp:~jelmer/brz/python3-weave-fmt.
392
            ('add', ('', b'root-id', 'directory', None)),
393
            ('add', ('file', b'file-id', 'file', b'content\nrev 1\n')),
6973.5.2 by Jelmer Vernooij
Add more bees.
394
            ], revision_id=b'rev-1')
6985 by Jelmer Vernooij
Merge lp:~jelmer/brz/python3-weave-fmt.
395
        builder.build_snapshot([b'rev-1'], [
396
            ('modify', ('file', b'content\nrev 2\n')),
6973.5.2 by Jelmer Vernooij
Add more bees.
397
            ], revision_id=b'rev-2')
6985 by Jelmer Vernooij
Merge lp:~jelmer/brz/python3-weave-fmt.
398
        builder.build_snapshot([b'rev-2'], [
399
            ('modify', ('file', b'content\nrev 3\n')),
6973.5.2 by Jelmer Vernooij
Add more bees.
400
            ], revision_id=b'rev-3')
5050.64.1 by Andrew Bennetts
Add reload-and-retry logic to RepositoryPackCollection.pack when a concurrent pack happens.
401
        self.addCleanup(builder.finish_series)
402
        b = builder.get_branch()
403
        self.addCleanup(b.lock_write().unlock)
404
        repo = b.repository
405
        collection = repo._pack_collection
406
        # Concurrently repack the repo.
6653.6.1 by Jelmer Vernooij
Rename a number of attributes from bzrdir to controldir.
407
        reopened_repo = repo.controldir.open_repository()
5050.64.1 by Andrew Bennetts
Add reload-and-retry logic to RepositoryPackCollection.pack when a concurrent pack happens.
408
        reopened_repo.pack()
409
        # Pack the new pack.
410
        collection.pack()
411
3789.2.11 by John Arbash Meinel
KnitVersionedFile.get_record_stream now retries *and* fails correctly.
412
    def make_vf_for_retrying(self):
3789.2.10 by John Arbash Meinel
The first function for KnitVersionedFiles can now retry on request.
413
        """Create 3 packs and a reload function.
414
415
        Originally, 2 pack files will have the data, but one will be missing.
416
        And then the third will be used in place of the first two if reload()
417
        is called.
418
419
        :return: (versioned_file, reload_counter)
420
            versioned_file  a KnitVersionedFiles using the packs for access
421
        """
4617.7.1 by Robert Collins
Lock the format knit retry tests depend on - knits aren't used for 2a formats.
422
        builder = self.make_branch_builder('.', format="1.9")
4454.3.59 by John Arbash Meinel
Track down why the annotate retry code was failing.
423
        builder.start_series()
6816.2.1 by Jelmer Vernooij
Migrate some build_snapshot code over to having revision_id as keyword argument.
424
        builder.build_snapshot(None, [
6985 by Jelmer Vernooij
Merge lp:~jelmer/brz/python3-weave-fmt.
425
            ('add', ('', b'root-id', 'directory', None)),
426
            ('add', ('file', b'file-id', 'file', b'content\nrev 1\n')),
6973.5.2 by Jelmer Vernooij
Add more bees.
427
            ], revision_id=b'rev-1')
6985 by Jelmer Vernooij
Merge lp:~jelmer/brz/python3-weave-fmt.
428
        builder.build_snapshot([b'rev-1'], [
429
            ('modify', ('file', b'content\nrev 2\n')),
6973.5.2 by Jelmer Vernooij
Add more bees.
430
            ], revision_id=b'rev-2')
6985 by Jelmer Vernooij
Merge lp:~jelmer/brz/python3-weave-fmt.
431
        builder.build_snapshot([b'rev-2'], [
432
            ('modify', ('file', b'content\nrev 3\n')),
6973.5.2 by Jelmer Vernooij
Add more bees.
433
            ], revision_id=b'rev-3')
4454.3.59 by John Arbash Meinel
Track down why the annotate retry code was failing.
434
        builder.finish_series()
435
        b = builder.get_branch()
436
        b.lock_write()
437
        self.addCleanup(b.unlock)
4145.1.6 by Robert Collins
More test fallout, but all caught now.
438
        # Pack these three revisions into another pack file, but don't remove
439
        # the originals
4454.3.59 by John Arbash Meinel
Track down why the annotate retry code was failing.
440
        repo = b.repository
4145.1.6 by Robert Collins
More test fallout, but all caught now.
441
        collection = repo._pack_collection
442
        collection.ensure_loaded()
443
        orig_packs = collection.packs
5757.7.3 by Jelmer Vernooij
Move more knitpack-specific functionality out of Packer.
444
        packer = knitpack_repo.KnitPacker(collection, orig_packs, '.testpack')
4145.1.6 by Robert Collins
More test fallout, but all caught now.
445
        new_pack = packer.pack()
446
        # forget about the new pack
447
        collection.reset()
448
        repo.refresh_data()
4454.3.59 by John Arbash Meinel
Track down why the annotate retry code was failing.
449
        vf = repo.revisions
3789.2.10 by John Arbash Meinel
The first function for KnitVersionedFiles can now retry on request.
450
        # Set up a reload() function that switches to using the new pack file
451
        new_index = new_pack.revision_index
452
        access_tuple = new_pack.access_tuple()
453
        reload_counter = [0, 0, 0]
7143.15.2 by Jelmer Vernooij
Run autopep8.
454
3789.2.10 by John Arbash Meinel
The first function for KnitVersionedFiles can now retry on request.
455
        def reload():
456
            reload_counter[0] += 1
457
            if reload_counter[1] > 0:
458
                # We already reloaded, nothing more to do
459
                reload_counter[2] += 1
460
                return False
461
            reload_counter[1] += 1
462
            vf._index._graph_index._indices[:] = [new_index]
463
            vf._access._indices.clear()
464
            vf._access._indices[new_index] = access_tuple
465
            return True
3789.2.11 by John Arbash Meinel
KnitVersionedFile.get_record_stream now retries *and* fails correctly.
466
        # Delete one of the pack files so the data will need to be reloaded. We
3789.2.12 by John Arbash Meinel
iter_lines_added_or_present now retries.
467
        # will delete the file with 'rev-2' in it
3789.2.10 by John Arbash Meinel
The first function for KnitVersionedFiles can now retry on request.
468
        trans, name = orig_packs[1].access_tuple()
469
        trans.delete(name)
470
        # We don't have the index trigger reloading because we want to test
471
        # that we reload when the .pack disappears
472
        vf._access._reload_func = reload
473
        return vf, reload_counter
474
3789.2.6 by John Arbash Meinel
Make _DirectPackAccess.reload_or_raise maintain the logic.
475
    def make_reload_func(self, return_val=True):
3789.2.5 by John Arbash Meinel
Change _DirectPackAccess to only raise Retry when _reload_func is defined.
476
        reload_called = [0]
7143.15.2 by Jelmer Vernooij
Run autopep8.
477
3789.2.5 by John Arbash Meinel
Change _DirectPackAccess to only raise Retry when _reload_func is defined.
478
        def reload():
479
            reload_called[0] += 1
3789.2.6 by John Arbash Meinel
Make _DirectPackAccess.reload_or_raise maintain the logic.
480
            return return_val
3789.2.5 by John Arbash Meinel
Change _DirectPackAccess to only raise Retry when _reload_func is defined.
481
        return reload_called, reload
482
3789.2.6 by John Arbash Meinel
Make _DirectPackAccess.reload_or_raise maintain the logic.
483
    def make_retry_exception(self):
484
        # We raise a real exception so that sys.exc_info() is properly
485
        # populated
486
        try:
487
            raise _TestException('foobar')
6619.3.2 by Jelmer Vernooij
Apply 2to3 except fix.
488
        except _TestException as e:
3789.2.29 by John Arbash Meinel
RetryWithNewPacks requires another argument.
489
            retry_exc = errors.RetryWithNewPacks(None, reload_occurred=False,
3789.2.6 by John Arbash Meinel
Make _DirectPackAccess.reload_or_raise maintain the logic.
490
                                                 exc_info=sys.exc_info())
5340.15.2 by John Arbash Meinel
supercede 2.4-613247-cleanup-tests
491
        # GZ 2010-08-10: Cycle with exc_info affects 3 tests
3789.2.6 by John Arbash Meinel
Make _DirectPackAccess.reload_or_raise maintain the logic.
492
        return retry_exc
493
2592.3.67 by Robert Collins
More tests for bzrlib.knit._PackAccess.
494
    def test_read_from_several_packs(self):
495
        access, writer = self._get_access()
496
        memos = []
6985 by Jelmer Vernooij
Merge lp:~jelmer/brz/python3-weave-fmt.
497
        memos.extend(access.add_raw_records([(b'key', 10)], b'1234567890'))
2592.3.67 by Robert Collins
More tests for bzrlib.knit._PackAccess.
498
        writer.end()
499
        access, writer = self._get_access('pack2', 'FOOBAR')
6985 by Jelmer Vernooij
Merge lp:~jelmer/brz/python3-weave-fmt.
500
        memos.extend(access.add_raw_records([(b'key', 5)], b'12345'))
2592.3.67 by Robert Collins
More tests for bzrlib.knit._PackAccess.
501
        writer.end()
502
        access, writer = self._get_access('pack3', 'BAZ')
6985 by Jelmer Vernooij
Merge lp:~jelmer/brz/python3-weave-fmt.
503
        memos.extend(access.add_raw_records([(b'key', 5)], b'alpha'))
2592.3.67 by Robert Collins
More tests for bzrlib.knit._PackAccess.
504
        writer.end()
505
        transport = self.get_transport()
7143.15.2 by Jelmer Vernooij
Run autopep8.
506
        access = pack_repo._DirectPackAccess({"FOO": (transport, 'packfile'),
507
                                              "FOOBAR": (transport, 'pack2'),
508
                                              "BAZ": (transport, 'pack3')})
6985 by Jelmer Vernooij
Merge lp:~jelmer/brz/python3-weave-fmt.
509
        self.assertEqual([b'1234567890', b'12345', b'alpha'],
7143.15.2 by Jelmer Vernooij
Run autopep8.
510
                         list(access.get_raw_records(memos)))
6985 by Jelmer Vernooij
Merge lp:~jelmer/brz/python3-weave-fmt.
511
        self.assertEqual([b'1234567890'],
7143.15.2 by Jelmer Vernooij
Run autopep8.
512
                         list(access.get_raw_records(memos[0:1])))
6985 by Jelmer Vernooij
Merge lp:~jelmer/brz/python3-weave-fmt.
513
        self.assertEqual([b'12345'],
7143.15.2 by Jelmer Vernooij
Run autopep8.
514
                         list(access.get_raw_records(memos[1:2])))
6985 by Jelmer Vernooij
Merge lp:~jelmer/brz/python3-weave-fmt.
515
        self.assertEqual([b'alpha'],
7143.15.2 by Jelmer Vernooij
Run autopep8.
516
                         list(access.get_raw_records(memos[2:3])))
6985 by Jelmer Vernooij
Merge lp:~jelmer/brz/python3-weave-fmt.
517
        self.assertEqual([b'1234567890', b'alpha'],
7143.15.2 by Jelmer Vernooij
Run autopep8.
518
                         list(access.get_raw_records(memos[0:1] + memos[2:3])))
2592.3.66 by Robert Collins
Allow adaption of KnitData to pack files.
519
2592.3.70 by Robert Collins
Allow setting a writer after creating a knit._PackAccess object.
520
    def test_set_writer(self):
521
        """The writer should be settable post construction."""
5757.5.1 by Jelmer Vernooij
Move _DirectPackAccess to bzrlib.repofmt.pack_repo.
522
        access = pack_repo._DirectPackAccess({})
2592.3.70 by Robert Collins
Allow setting a writer after creating a knit._PackAccess object.
523
        transport = self.get_transport()
524
        packname = 'packfile'
525
        index = 'foo'
7143.15.2 by Jelmer Vernooij
Run autopep8.
526
2592.3.70 by Robert Collins
Allow setting a writer after creating a knit._PackAccess object.
527
        def write_data(bytes):
528
            transport.append_bytes(packname, bytes)
529
        writer = pack.ContainerWriter(write_data)
530
        writer.begin()
531
        access.set_writer(writer, index, (transport, packname))
6985 by Jelmer Vernooij
Merge lp:~jelmer/brz/python3-weave-fmt.
532
        memos = access.add_raw_records([(b'key', 10)], b'1234567890')
2592.3.70 by Robert Collins
Allow setting a writer after creating a knit._PackAccess object.
533
        writer.end()
6985 by Jelmer Vernooij
Merge lp:~jelmer/brz/python3-weave-fmt.
534
        self.assertEqual([b'1234567890'], list(access.get_raw_records(memos)))
2592.3.70 by Robert Collins
Allow setting a writer after creating a knit._PackAccess object.
535
3789.2.1 by John Arbash Meinel
_DirectPackAccess can now raise RetryWithNewPacks when we think something has happened.
536
    def test_missing_index_raises_retry(self):
3789.2.5 by John Arbash Meinel
Change _DirectPackAccess to only raise Retry when _reload_func is defined.
537
        memos = self.make_pack_file()
3789.2.1 by John Arbash Meinel
_DirectPackAccess can now raise RetryWithNewPacks when we think something has happened.
538
        transport = self.get_transport()
3789.2.5 by John Arbash Meinel
Change _DirectPackAccess to only raise Retry when _reload_func is defined.
539
        reload_called, reload_func = self.make_reload_func()
540
        # Note that the index key has changed from 'foo' to 'bar'
7143.15.2 by Jelmer Vernooij
Run autopep8.
541
        access = pack_repo._DirectPackAccess({'bar': (transport, 'packname')},
542
                                             reload_func=reload_func)
3789.2.1 by John Arbash Meinel
_DirectPackAccess can now raise RetryWithNewPacks when we think something has happened.
543
        e = self.assertListRaises(errors.RetryWithNewPacks,
544
                                  access.get_raw_records, memos)
545
        # Because a key was passed in which does not match our index list, we
546
        # assume that the listing was already reloaded
547
        self.assertTrue(e.reload_occurred)
548
        self.assertIsInstance(e.exc_info, tuple)
549
        self.assertIs(e.exc_info[0], KeyError)
550
        self.assertIsInstance(e.exc_info[1], KeyError)
551
3789.2.5 by John Arbash Meinel
Change _DirectPackAccess to only raise Retry when _reload_func is defined.
552
    def test_missing_index_raises_key_error_with_no_reload(self):
553
        memos = self.make_pack_file()
554
        transport = self.get_transport()
555
        # Note that the index key has changed from 'foo' to 'bar'
7143.15.2 by Jelmer Vernooij
Run autopep8.
556
        access = pack_repo._DirectPackAccess({'bar': (transport, 'packname')})
3789.2.5 by John Arbash Meinel
Change _DirectPackAccess to only raise Retry when _reload_func is defined.
557
        e = self.assertListRaises(KeyError, access.get_raw_records, memos)
558
3789.2.1 by John Arbash Meinel
_DirectPackAccess can now raise RetryWithNewPacks when we think something has happened.
559
    def test_missing_file_raises_retry(self):
3789.2.5 by John Arbash Meinel
Change _DirectPackAccess to only raise Retry when _reload_func is defined.
560
        memos = self.make_pack_file()
561
        transport = self.get_transport()
562
        reload_called, reload_func = self.make_reload_func()
563
        # Note that the 'filename' has been changed to 'different-packname'
5757.5.1 by Jelmer Vernooij
Move _DirectPackAccess to bzrlib.repofmt.pack_repo.
564
        access = pack_repo._DirectPackAccess(
7143.15.2 by Jelmer Vernooij
Run autopep8.
565
            {'foo': (transport, 'different-packname')},
5757.8.1 by Jelmer Vernooij
Avoid bzrlib.knit imports when using groupcompress repositories.
566
            reload_func=reload_func)
3789.2.5 by John Arbash Meinel
Change _DirectPackAccess to only raise Retry when _reload_func is defined.
567
        e = self.assertListRaises(errors.RetryWithNewPacks,
568
                                  access.get_raw_records, memos)
569
        # The file has gone missing, so we assume we need to reload
570
        self.assertFalse(e.reload_occurred)
571
        self.assertIsInstance(e.exc_info, tuple)
572
        self.assertIs(e.exc_info[0], errors.NoSuchFile)
573
        self.assertIsInstance(e.exc_info[1], errors.NoSuchFile)
574
        self.assertEqual('different-packname', e.exc_info[1].path)
575
576
    def test_missing_file_raises_no_such_file_with_no_reload(self):
577
        memos = self.make_pack_file()
578
        transport = self.get_transport()
579
        # Note that the 'filename' has been changed to 'different-packname'
5757.5.1 by Jelmer Vernooij
Move _DirectPackAccess to bzrlib.repofmt.pack_repo.
580
        access = pack_repo._DirectPackAccess(
5757.5.2 by Jelmer Vernooij
merge bzr.dev.
581
            {'foo': (transport, 'different-packname')})
3789.2.5 by John Arbash Meinel
Change _DirectPackAccess to only raise Retry when _reload_func is defined.
582
        e = self.assertListRaises(errors.NoSuchFile,
3789.2.1 by John Arbash Meinel
_DirectPackAccess can now raise RetryWithNewPacks when we think something has happened.
583
                                  access.get_raw_records, memos)
584
3789.2.2 by John Arbash Meinel
Test that a readv() failing after yielding data will still raise Retry
585
    def test_failing_readv_raises_retry(self):
3789.2.5 by John Arbash Meinel
Change _DirectPackAccess to only raise Retry when _reload_func is defined.
586
        memos = self.make_pack_file()
587
        transport = self.get_transport()
588
        failing_transport = MockReadvFailingTransport(
7143.15.2 by Jelmer Vernooij
Run autopep8.
589
            [transport.get_bytes('packname')])
3789.2.5 by John Arbash Meinel
Change _DirectPackAccess to only raise Retry when _reload_func is defined.
590
        reload_called, reload_func = self.make_reload_func()
5757.5.1 by Jelmer Vernooij
Move _DirectPackAccess to bzrlib.repofmt.pack_repo.
591
        access = pack_repo._DirectPackAccess(
5757.5.2 by Jelmer Vernooij
merge bzr.dev.
592
            {'foo': (failing_transport, 'packname')},
5757.8.1 by Jelmer Vernooij
Avoid bzrlib.knit imports when using groupcompress repositories.
593
            reload_func=reload_func)
3789.2.5 by John Arbash Meinel
Change _DirectPackAccess to only raise Retry when _reload_func is defined.
594
        # Asking for a single record will not trigger the Mock failure
6985 by Jelmer Vernooij
Merge lp:~jelmer/brz/python3-weave-fmt.
595
        self.assertEqual([b'1234567890'],
7143.15.2 by Jelmer Vernooij
Run autopep8.
596
                         list(access.get_raw_records(memos[:1])))
6985 by Jelmer Vernooij
Merge lp:~jelmer/brz/python3-weave-fmt.
597
        self.assertEqual([b'12345'],
7143.15.2 by Jelmer Vernooij
Run autopep8.
598
                         list(access.get_raw_records(memos[1:2])))
3789.2.5 by John Arbash Meinel
Change _DirectPackAccess to only raise Retry when _reload_func is defined.
599
        # A multiple offset readv() will fail mid-way through
600
        e = self.assertListRaises(errors.RetryWithNewPacks,
601
                                  access.get_raw_records, memos)
602
        # The file has gone missing, so we assume we need to reload
603
        self.assertFalse(e.reload_occurred)
604
        self.assertIsInstance(e.exc_info, tuple)
605
        self.assertIs(e.exc_info[0], errors.NoSuchFile)
606
        self.assertIsInstance(e.exc_info[1], errors.NoSuchFile)
607
        self.assertEqual('packname', e.exc_info[1].path)
608
609
    def test_failing_readv_raises_no_such_file_with_no_reload(self):
610
        memos = self.make_pack_file()
611
        transport = self.get_transport()
612
        failing_transport = MockReadvFailingTransport(
7143.15.2 by Jelmer Vernooij
Run autopep8.
613
            [transport.get_bytes('packname')])
3789.2.5 by John Arbash Meinel
Change _DirectPackAccess to only raise Retry when _reload_func is defined.
614
        reload_called, reload_func = self.make_reload_func()
5757.5.1 by Jelmer Vernooij
Move _DirectPackAccess to bzrlib.repofmt.pack_repo.
615
        access = pack_repo._DirectPackAccess(
7143.15.2 by Jelmer Vernooij
Run autopep8.
616
            {'foo': (failing_transport, 'packname')})
3789.2.3 by John Arbash Meinel
Change the mocking a bit, so we can be sure it is failing at the right time.
617
        # Asking for a single record will not trigger the Mock failure
6985 by Jelmer Vernooij
Merge lp:~jelmer/brz/python3-weave-fmt.
618
        self.assertEqual([b'1234567890'],
7143.15.2 by Jelmer Vernooij
Run autopep8.
619
                         list(access.get_raw_records(memos[:1])))
6985 by Jelmer Vernooij
Merge lp:~jelmer/brz/python3-weave-fmt.
620
        self.assertEqual([b'12345'],
7143.15.2 by Jelmer Vernooij
Run autopep8.
621
                         list(access.get_raw_records(memos[1:2])))
3789.2.3 by John Arbash Meinel
Change the mocking a bit, so we can be sure it is failing at the right time.
622
        # A multiple offset readv() will fail mid-way through
3789.2.5 by John Arbash Meinel
Change _DirectPackAccess to only raise Retry when _reload_func is defined.
623
        e = self.assertListRaises(errors.NoSuchFile,
3789.2.2 by John Arbash Meinel
Test that a readv() failing after yielding data will still raise Retry
624
                                  access.get_raw_records, memos)
625
3789.2.6 by John Arbash Meinel
Make _DirectPackAccess.reload_or_raise maintain the logic.
626
    def test_reload_or_raise_no_reload(self):
5757.5.1 by Jelmer Vernooij
Move _DirectPackAccess to bzrlib.repofmt.pack_repo.
627
        access = pack_repo._DirectPackAccess({}, reload_func=None)
3789.2.6 by John Arbash Meinel
Make _DirectPackAccess.reload_or_raise maintain the logic.
628
        retry_exc = self.make_retry_exception()
629
        # Without a reload_func, we will just re-raise the original exception
630
        self.assertRaises(_TestException, access.reload_or_raise, retry_exc)
631
632
    def test_reload_or_raise_reload_changed(self):
633
        reload_called, reload_func = self.make_reload_func(return_val=True)
5757.5.1 by Jelmer Vernooij
Move _DirectPackAccess to bzrlib.repofmt.pack_repo.
634
        access = pack_repo._DirectPackAccess({}, reload_func=reload_func)
3789.2.6 by John Arbash Meinel
Make _DirectPackAccess.reload_or_raise maintain the logic.
635
        retry_exc = self.make_retry_exception()
636
        access.reload_or_raise(retry_exc)
637
        self.assertEqual([1], reload_called)
7143.15.2 by Jelmer Vernooij
Run autopep8.
638
        retry_exc.reload_occurred = True
3789.2.6 by John Arbash Meinel
Make _DirectPackAccess.reload_or_raise maintain the logic.
639
        access.reload_or_raise(retry_exc)
640
        self.assertEqual([2], reload_called)
641
642
    def test_reload_or_raise_reload_no_change(self):
643
        reload_called, reload_func = self.make_reload_func(return_val=False)
5757.5.1 by Jelmer Vernooij
Move _DirectPackAccess to bzrlib.repofmt.pack_repo.
644
        access = pack_repo._DirectPackAccess({}, reload_func=reload_func)
3789.2.6 by John Arbash Meinel
Make _DirectPackAccess.reload_or_raise maintain the logic.
645
        retry_exc = self.make_retry_exception()
646
        # If reload_occurred is False, then we consider it an error to have
647
        # reload_func() return False (no changes).
648
        self.assertRaises(_TestException, access.reload_or_raise, retry_exc)
649
        self.assertEqual([1], reload_called)
7143.15.2 by Jelmer Vernooij
Run autopep8.
650
        retry_exc.reload_occurred = True
3789.2.6 by John Arbash Meinel
Make _DirectPackAccess.reload_or_raise maintain the logic.
651
        # If reload_occurred is True, then we assume nothing changed because
652
        # it had changed earlier, but didn't change again
653
        access.reload_or_raise(retry_exc)
654
        self.assertEqual([2], reload_called)
655
3789.2.13 by John Arbash Meinel
KnitVersionedFile.annotate() now retries when appropriate.
656
    def test_annotate_retries(self):
657
        vf, reload_counter = self.make_vf_for_retrying()
658
        # It is a little bit bogus to annotate the Revision VF, but it works,
659
        # as we have ancestry stored there
6985 by Jelmer Vernooij
Merge lp:~jelmer/brz/python3-weave-fmt.
660
        key = (b'rev-3',)
3789.2.13 by John Arbash Meinel
KnitVersionedFile.annotate() now retries when appropriate.
661
        reload_lines = vf.annotate(key)
662
        self.assertEqual([1, 1, 0], reload_counter)
663
        plain_lines = vf.annotate(key)
7143.15.2 by Jelmer Vernooij
Run autopep8.
664
        self.assertEqual([1, 1, 0], reload_counter)  # No extra reloading
3789.2.13 by John Arbash Meinel
KnitVersionedFile.annotate() now retries when appropriate.
665
        if reload_lines != plain_lines:
666
            self.fail('Annotation was not identical with reloading.')
667
        # Now delete the packs-in-use, which should trigger another reload, but
668
        # this time we just raise an exception because we can't recover
6656.1.1 by Martin
Apply 2to3 dict fixer and clean up resulting mess using view helpers
669
        for trans, name in vf._access._indices.values():
3789.2.13 by John Arbash Meinel
KnitVersionedFile.annotate() now retries when appropriate.
670
            trans.delete(name)
671
        self.assertRaises(errors.NoSuchFile, vf.annotate, key)
672
        self.assertEqual([2, 1, 1], reload_counter)
673
3789.2.10 by John Arbash Meinel
The first function for KnitVersionedFiles can now retry on request.
674
    def test__get_record_map_retries(self):
3789.2.11 by John Arbash Meinel
KnitVersionedFile.get_record_stream now retries *and* fails correctly.
675
        vf, reload_counter = self.make_vf_for_retrying()
6985 by Jelmer Vernooij
Merge lp:~jelmer/brz/python3-weave-fmt.
676
        keys = [(b'rev-1',), (b'rev-2',), (b'rev-3',)]
3789.2.10 by John Arbash Meinel
The first function for KnitVersionedFiles can now retry on request.
677
        records = vf._get_record_map(keys)
678
        self.assertEqual(keys, sorted(records.keys()))
3789.2.11 by John Arbash Meinel
KnitVersionedFile.get_record_stream now retries *and* fails correctly.
679
        self.assertEqual([1, 1, 0], reload_counter)
680
        # Now delete the packs-in-use, which should trigger another reload, but
681
        # this time we just raise an exception because we can't recover
6656.1.1 by Martin
Apply 2to3 dict fixer and clean up resulting mess using view helpers
682
        for trans, name in vf._access._indices.values():
3789.2.11 by John Arbash Meinel
KnitVersionedFile.get_record_stream now retries *and* fails correctly.
683
            trans.delete(name)
684
        self.assertRaises(errors.NoSuchFile, vf._get_record_map, keys)
685
        self.assertEqual([2, 1, 1], reload_counter)
686
687
    def test_get_record_stream_retries(self):
688
        vf, reload_counter = self.make_vf_for_retrying()
6985 by Jelmer Vernooij
Merge lp:~jelmer/brz/python3-weave-fmt.
689
        keys = [(b'rev-1',), (b'rev-2',), (b'rev-3',)]
3789.2.11 by John Arbash Meinel
KnitVersionedFile.get_record_stream now retries *and* fails correctly.
690
        record_stream = vf.get_record_stream(keys, 'topological', False)
6634.2.1 by Martin
Apply 2to3 next fixer and make compatible
691
        record = next(record_stream)
6985 by Jelmer Vernooij
Merge lp:~jelmer/brz/python3-weave-fmt.
692
        self.assertEqual((b'rev-1',), record.key)
3789.2.11 by John Arbash Meinel
KnitVersionedFile.get_record_stream now retries *and* fails correctly.
693
        self.assertEqual([0, 0, 0], reload_counter)
6634.2.1 by Martin
Apply 2to3 next fixer and make compatible
694
        record = next(record_stream)
6985 by Jelmer Vernooij
Merge lp:~jelmer/brz/python3-weave-fmt.
695
        self.assertEqual((b'rev-2',), record.key)
3789.2.11 by John Arbash Meinel
KnitVersionedFile.get_record_stream now retries *and* fails correctly.
696
        self.assertEqual([1, 1, 0], reload_counter)
6634.2.1 by Martin
Apply 2to3 next fixer and make compatible
697
        record = next(record_stream)
6985 by Jelmer Vernooij
Merge lp:~jelmer/brz/python3-weave-fmt.
698
        self.assertEqual((b'rev-3',), record.key)
3789.2.12 by John Arbash Meinel
iter_lines_added_or_present now retries.
699
        self.assertEqual([1, 1, 0], reload_counter)
3789.2.11 by John Arbash Meinel
KnitVersionedFile.get_record_stream now retries *and* fails correctly.
700
        # Now delete all pack files, and see that we raise the right error
6656.1.1 by Martin
Apply 2to3 dict fixer and clean up resulting mess using view helpers
701
        for trans, name in vf._access._indices.values():
3789.2.11 by John Arbash Meinel
KnitVersionedFile.get_record_stream now retries *and* fails correctly.
702
            trans.delete(name)
703
        self.assertListRaises(errors.NoSuchFile,
7143.15.2 by Jelmer Vernooij
Run autopep8.
704
                              vf.get_record_stream, keys, 'topological', False)
3789.2.11 by John Arbash Meinel
KnitVersionedFile.get_record_stream now retries *and* fails correctly.
705
3789.2.12 by John Arbash Meinel
iter_lines_added_or_present now retries.
706
    def test_iter_lines_added_or_present_in_keys_retries(self):
707
        vf, reload_counter = self.make_vf_for_retrying()
6985 by Jelmer Vernooij
Merge lp:~jelmer/brz/python3-weave-fmt.
708
        keys = [(b'rev-1',), (b'rev-2',), (b'rev-3',)]
3789.2.12 by John Arbash Meinel
iter_lines_added_or_present now retries.
709
        # Unfortunately, iter_lines_added_or_present_in_keys iterates the
710
        # result in random order (determined by the iteration order from a
711
        # set()), so we don't have any solid way to trigger whether data is
712
        # read before or after. However we tried to delete the middle node to
713
        # exercise the code well.
714
        # What we care about is that all lines are always yielded, but not
715
        # duplicated
716
        count = 0
717
        reload_lines = sorted(vf.iter_lines_added_or_present_in_keys(keys))
718
        self.assertEqual([1, 1, 0], reload_counter)
719
        # Now do it again, to make sure the result is equivalent
720
        plain_lines = sorted(vf.iter_lines_added_or_present_in_keys(keys))
7143.15.2 by Jelmer Vernooij
Run autopep8.
721
        self.assertEqual([1, 1, 0], reload_counter)  # No extra reloading
3789.2.12 by John Arbash Meinel
iter_lines_added_or_present now retries.
722
        self.assertEqual(plain_lines, reload_lines)
723
        self.assertEqual(21, len(plain_lines))
724
        # Now delete all pack files, and see that we raise the right error
6656.1.1 by Martin
Apply 2to3 dict fixer and clean up resulting mess using view helpers
725
        for trans, name in vf._access._indices.values():
3789.2.12 by John Arbash Meinel
iter_lines_added_or_present now retries.
726
            trans.delete(name)
727
        self.assertListRaises(errors.NoSuchFile,
7143.15.2 by Jelmer Vernooij
Run autopep8.
728
                              vf.iter_lines_added_or_present_in_keys, keys)
3789.2.12 by John Arbash Meinel
iter_lines_added_or_present now retries.
729
        self.assertEqual([2, 1, 1], reload_counter)
730
3878.1.1 by John Arbash Meinel
KVF.get_record_stream('unordered') now returns the records based on I/O ordering.
731
    def test_get_record_stream_yields_disk_sorted_order(self):
732
        # if we get 'unordered' pick a semi-optimal order for reading. The
733
        # order should be grouped by pack file, and then by position in file
734
        repo = self.make_repository('test', format='pack-0.92')
735
        repo.lock_write()
736
        self.addCleanup(repo.unlock)
737
        repo.start_write_group()
738
        vf = repo.texts
6985 by Jelmer Vernooij
Merge lp:~jelmer/brz/python3-weave-fmt.
739
        vf.add_lines((b'f-id', b'rev-5'), [(b'f-id', b'rev-4')], [b'lines\n'])
740
        vf.add_lines((b'f-id', b'rev-1'), [], [b'lines\n'])
741
        vf.add_lines((b'f-id', b'rev-2'), [(b'f-id', b'rev-1')], [b'lines\n'])
3878.1.1 by John Arbash Meinel
KVF.get_record_stream('unordered') now returns the records based on I/O ordering.
742
        repo.commit_write_group()
743
        # We inserted them as rev-5, rev-1, rev-2, we should get them back in
744
        # the same order
6973.13.2 by Jelmer Vernooij
Fix some more tests.
745
        stream = vf.get_record_stream([(b'f-id', b'rev-1'), (b'f-id', b'rev-5'),
746
                                       (b'f-id', b'rev-2')], 'unordered', False)
3878.1.1 by John Arbash Meinel
KVF.get_record_stream('unordered') now returns the records based on I/O ordering.
747
        keys = [r.key for r in stream]
6973.13.2 by Jelmer Vernooij
Fix some more tests.
748
        self.assertEqual([(b'f-id', b'rev-5'), (b'f-id', b'rev-1'),
749
                          (b'f-id', b'rev-2')], keys)
3878.1.1 by John Arbash Meinel
KVF.get_record_stream('unordered') now returns the records based on I/O ordering.
750
        repo.start_write_group()
6973.13.2 by Jelmer Vernooij
Fix some more tests.
751
        vf.add_lines((b'f-id', b'rev-4'), [(b'f-id', b'rev-3')], [b'lines\n'])
752
        vf.add_lines((b'f-id', b'rev-3'), [(b'f-id', b'rev-2')], [b'lines\n'])
753
        vf.add_lines((b'f-id', b'rev-6'), [(b'f-id', b'rev-5')], [b'lines\n'])
3878.1.1 by John Arbash Meinel
KVF.get_record_stream('unordered') now returns the records based on I/O ordering.
754
        repo.commit_write_group()
755
        # Request in random order, to make sure the output order isn't based on
756
        # the request
6973.13.2 by Jelmer Vernooij
Fix some more tests.
757
        request_keys = set((b'f-id', b'rev-%d' % i) for i in range(1, 7))
3878.1.1 by John Arbash Meinel
KVF.get_record_stream('unordered') now returns the records based on I/O ordering.
758
        stream = vf.get_record_stream(request_keys, 'unordered', False)
759
        keys = [r.key for r in stream]
760
        # We want to get the keys back in disk order, but it doesn't matter
761
        # which pack we read from first. So this can come back in 2 orders
6973.13.2 by Jelmer Vernooij
Fix some more tests.
762
        alt1 = [(b'f-id', b'rev-%d' % i) for i in [4, 3, 6, 5, 1, 2]]
763
        alt2 = [(b'f-id', b'rev-%d' % i) for i in [5, 1, 2, 4, 3, 6]]
3878.1.1 by John Arbash Meinel
KVF.get_record_stream('unordered') now returns the records based on I/O ordering.
764
        if keys != alt1 and keys != alt2:
765
            self.fail('Returned key order did not match either expected order.'
766
                      ' expected %s or %s, not %s'
767
                      % (alt1, alt2, keys))
768
2592.3.66 by Robert Collins
Allow adaption of KnitData to pack files.
769
2329.1.1 by John Arbash Meinel
Update _KnitData parser to raise more helpful errors when it detects corruption.
770
class LowLevelKnitDataTests(TestCase):
771
772
    def create_gz_content(self, text):
6621.22.2 by Martin
Use BytesIO or StringIO from bzrlib.sixish
773
        sio = BytesIO()
6973.14.6 by Jelmer Vernooij
Fix some more tests.
774
        with gzip.GzipFile(mode='wb', fileobj=sio) as gz_file:
775
            gz_file.write(text)
2329.1.1 by John Arbash Meinel
Update _KnitData parser to raise more helpful errors when it detects corruption.
776
        return sio.getvalue()
777
3789.2.4 by John Arbash Meinel
Add a multiple-record test, though it isn't quite what we want for the readv tests.
778
    def make_multiple_records(self):
779
        """Create the content for multiple records."""
6985 by Jelmer Vernooij
Merge lp:~jelmer/brz/python3-weave-fmt.
780
        sha1sum = osutils.sha_string(b'foo\nbar\n')
3789.2.4 by John Arbash Meinel
Add a multiple-record test, though it isn't quite what we want for the readv tests.
781
        total_txt = []
6985 by Jelmer Vernooij
Merge lp:~jelmer/brz/python3-weave-fmt.
782
        gz_txt = self.create_gz_content(b'version rev-id-1 2 %s\n'
783
                                        b'foo\n'
784
                                        b'bar\n'
785
                                        b'end rev-id-1\n'
3789.2.4 by John Arbash Meinel
Add a multiple-record test, though it isn't quite what we want for the readv tests.
786
                                        % (sha1sum,))
787
        record_1 = (0, len(gz_txt), sha1sum)
788
        total_txt.append(gz_txt)
6985 by Jelmer Vernooij
Merge lp:~jelmer/brz/python3-weave-fmt.
789
        sha1sum = osutils.sha_string(b'baz\n')
790
        gz_txt = self.create_gz_content(b'version rev-id-2 1 %s\n'
791
                                        b'baz\n'
792
                                        b'end rev-id-2\n'
3789.2.4 by John Arbash Meinel
Add a multiple-record test, though it isn't quite what we want for the readv tests.
793
                                        % (sha1sum,))
794
        record_2 = (record_1[1], len(gz_txt), sha1sum)
795
        total_txt.append(gz_txt)
796
        return total_txt, record_1, record_2
797
2329.1.1 by John Arbash Meinel
Update _KnitData parser to raise more helpful errors when it detects corruption.
798
    def test_valid_knit_data(self):
6985 by Jelmer Vernooij
Merge lp:~jelmer/brz/python3-weave-fmt.
799
        sha1sum = osutils.sha_string(b'foo\nbar\n')
800
        gz_txt = self.create_gz_content(b'version rev-id-1 2 %s\n'
801
                                        b'foo\n'
802
                                        b'bar\n'
803
                                        b'end rev-id-1\n'
2329.1.1 by John Arbash Meinel
Update _KnitData parser to raise more helpful errors when it detects corruption.
804
                                        % (sha1sum,))
805
        transport = MockTransport([gz_txt])
3350.6.4 by Robert Collins
First cut at pluralised VersionedFiles. Some rather massive API incompatabilities, primarily because of the difficulty of coherence among competing stores.
806
        access = _KnitKeyAccess(transport, ConstantMapper('filename'))
807
        knit = KnitVersionedFiles(None, access)
6985 by Jelmer Vernooij
Merge lp:~jelmer/brz/python3-weave-fmt.
808
        records = [((b'rev-id-1',), ((b'rev-id-1',), 0, len(gz_txt)))]
3350.6.4 by Robert Collins
First cut at pluralised VersionedFiles. Some rather massive API incompatabilities, primarily because of the difficulty of coherence among competing stores.
809
810
        contents = list(knit._read_records_iter(records))
6985 by Jelmer Vernooij
Merge lp:~jelmer/brz/python3-weave-fmt.
811
        self.assertEqual([((b'rev-id-1',), [b'foo\n', b'bar\n'],
7143.15.2 by Jelmer Vernooij
Run autopep8.
812
                           b'4e48e2c9a3d2ca8a708cb0cc545700544efb5021')], contents)
3350.6.4 by Robert Collins
First cut at pluralised VersionedFiles. Some rather massive API incompatabilities, primarily because of the difficulty of coherence among competing stores.
813
814
        raw_contents = list(knit._read_records_iter_raw(records))
6985 by Jelmer Vernooij
Merge lp:~jelmer/brz/python3-weave-fmt.
815
        self.assertEqual([((b'rev-id-1',), gz_txt, sha1sum)], raw_contents)
2329.1.1 by John Arbash Meinel
Update _KnitData parser to raise more helpful errors when it detects corruption.
816
3789.2.4 by John Arbash Meinel
Add a multiple-record test, though it isn't quite what we want for the readv tests.
817
    def test_multiple_records_valid(self):
818
        total_txt, record_1, record_2 = self.make_multiple_records()
6985 by Jelmer Vernooij
Merge lp:~jelmer/brz/python3-weave-fmt.
819
        transport = MockTransport([b''.join(total_txt)])
3789.2.4 by John Arbash Meinel
Add a multiple-record test, though it isn't quite what we want for the readv tests.
820
        access = _KnitKeyAccess(transport, ConstantMapper('filename'))
821
        knit = KnitVersionedFiles(None, access)
6985 by Jelmer Vernooij
Merge lp:~jelmer/brz/python3-weave-fmt.
822
        records = [((b'rev-id-1',), ((b'rev-id-1',), record_1[0], record_1[1])),
823
                   ((b'rev-id-2',), ((b'rev-id-2',), record_2[0], record_2[1]))]
3789.2.4 by John Arbash Meinel
Add a multiple-record test, though it isn't quite what we want for the readv tests.
824
825
        contents = list(knit._read_records_iter(records))
6985 by Jelmer Vernooij
Merge lp:~jelmer/brz/python3-weave-fmt.
826
        self.assertEqual([((b'rev-id-1',), [b'foo\n', b'bar\n'], record_1[2]),
827
                          ((b'rev-id-2',), [b'baz\n'], record_2[2])],
3789.2.4 by John Arbash Meinel
Add a multiple-record test, though it isn't quite what we want for the readv tests.
828
                         contents)
829
830
        raw_contents = list(knit._read_records_iter_raw(records))
6985 by Jelmer Vernooij
Merge lp:~jelmer/brz/python3-weave-fmt.
831
        self.assertEqual([((b'rev-id-1',), total_txt[0], record_1[2]),
832
                          ((b'rev-id-2',), total_txt[1], record_2[2])],
3789.2.4 by John Arbash Meinel
Add a multiple-record test, though it isn't quite what we want for the readv tests.
833
                         raw_contents)
834
2329.1.1 by John Arbash Meinel
Update _KnitData parser to raise more helpful errors when it detects corruption.
835
    def test_not_enough_lines(self):
6985 by Jelmer Vernooij
Merge lp:~jelmer/brz/python3-weave-fmt.
836
        sha1sum = osutils.sha_string(b'foo\n')
2329.1.1 by John Arbash Meinel
Update _KnitData parser to raise more helpful errors when it detects corruption.
837
        # record says 2 lines data says 1
6985 by Jelmer Vernooij
Merge lp:~jelmer/brz/python3-weave-fmt.
838
        gz_txt = self.create_gz_content(b'version rev-id-1 2 %s\n'
839
                                        b'foo\n'
840
                                        b'end rev-id-1\n'
2329.1.1 by John Arbash Meinel
Update _KnitData parser to raise more helpful errors when it detects corruption.
841
                                        % (sha1sum,))
842
        transport = MockTransport([gz_txt])
3350.6.4 by Robert Collins
First cut at pluralised VersionedFiles. Some rather massive API incompatabilities, primarily because of the difficulty of coherence among competing stores.
843
        access = _KnitKeyAccess(transport, ConstantMapper('filename'))
844
        knit = KnitVersionedFiles(None, access)
6985 by Jelmer Vernooij
Merge lp:~jelmer/brz/python3-weave-fmt.
845
        records = [((b'rev-id-1',), ((b'rev-id-1',), 0, len(gz_txt)))]
6729.7.2 by Jelmer Vernooij
Finish move.
846
        self.assertRaises(KnitCorrupt, list,
7143.15.2 by Jelmer Vernooij
Run autopep8.
847
                          knit._read_records_iter(records))
2329.1.1 by John Arbash Meinel
Update _KnitData parser to raise more helpful errors when it detects corruption.
848
849
        # read_records_iter_raw won't detect that sort of mismatch/corruption
3350.6.4 by Robert Collins
First cut at pluralised VersionedFiles. Some rather massive API incompatabilities, primarily because of the difficulty of coherence among competing stores.
850
        raw_contents = list(knit._read_records_iter_raw(records))
7143.15.2 by Jelmer Vernooij
Run autopep8.
851
        self.assertEqual([((b'rev-id-1',), gz_txt, sha1sum)], raw_contents)
2329.1.1 by John Arbash Meinel
Update _KnitData parser to raise more helpful errors when it detects corruption.
852
853
    def test_too_many_lines(self):
6985 by Jelmer Vernooij
Merge lp:~jelmer/brz/python3-weave-fmt.
854
        sha1sum = osutils.sha_string(b'foo\nbar\n')
2329.1.1 by John Arbash Meinel
Update _KnitData parser to raise more helpful errors when it detects corruption.
855
        # record says 1 lines data says 2
6985 by Jelmer Vernooij
Merge lp:~jelmer/brz/python3-weave-fmt.
856
        gz_txt = self.create_gz_content(b'version rev-id-1 1 %s\n'
857
                                        b'foo\n'
858
                                        b'bar\n'
859
                                        b'end rev-id-1\n'
2329.1.1 by John Arbash Meinel
Update _KnitData parser to raise more helpful errors when it detects corruption.
860
                                        % (sha1sum,))
861
        transport = MockTransport([gz_txt])
3350.6.4 by Robert Collins
First cut at pluralised VersionedFiles. Some rather massive API incompatabilities, primarily because of the difficulty of coherence among competing stores.
862
        access = _KnitKeyAccess(transport, ConstantMapper('filename'))
863
        knit = KnitVersionedFiles(None, access)
6985 by Jelmer Vernooij
Merge lp:~jelmer/brz/python3-weave-fmt.
864
        records = [((b'rev-id-1',), ((b'rev-id-1',), 0, len(gz_txt)))]
6729.7.2 by Jelmer Vernooij
Finish move.
865
        self.assertRaises(KnitCorrupt, list,
7143.15.2 by Jelmer Vernooij
Run autopep8.
866
                          knit._read_records_iter(records))
2329.1.1 by John Arbash Meinel
Update _KnitData parser to raise more helpful errors when it detects corruption.
867
868
        # read_records_iter_raw won't detect that sort of mismatch/corruption
3350.6.4 by Robert Collins
First cut at pluralised VersionedFiles. Some rather massive API incompatabilities, primarily because of the difficulty of coherence among competing stores.
869
        raw_contents = list(knit._read_records_iter_raw(records))
6985 by Jelmer Vernooij
Merge lp:~jelmer/brz/python3-weave-fmt.
870
        self.assertEqual([((b'rev-id-1',), gz_txt, sha1sum)], raw_contents)
2329.1.1 by John Arbash Meinel
Update _KnitData parser to raise more helpful errors when it detects corruption.
871
872
    def test_mismatched_version_id(self):
6985 by Jelmer Vernooij
Merge lp:~jelmer/brz/python3-weave-fmt.
873
        sha1sum = osutils.sha_string(b'foo\nbar\n')
874
        gz_txt = self.create_gz_content(b'version rev-id-1 2 %s\n'
875
                                        b'foo\n'
876
                                        b'bar\n'
877
                                        b'end rev-id-1\n'
2329.1.1 by John Arbash Meinel
Update _KnitData parser to raise more helpful errors when it detects corruption.
878
                                        % (sha1sum,))
879
        transport = MockTransport([gz_txt])
3350.6.4 by Robert Collins
First cut at pluralised VersionedFiles. Some rather massive API incompatabilities, primarily because of the difficulty of coherence among competing stores.
880
        access = _KnitKeyAccess(transport, ConstantMapper('filename'))
881
        knit = KnitVersionedFiles(None, access)
2329.1.1 by John Arbash Meinel
Update _KnitData parser to raise more helpful errors when it detects corruption.
882
        # We are asking for rev-id-2, but the data is rev-id-1
6985 by Jelmer Vernooij
Merge lp:~jelmer/brz/python3-weave-fmt.
883
        records = [((b'rev-id-2',), ((b'rev-id-2',), 0, len(gz_txt)))]
6729.7.2 by Jelmer Vernooij
Finish move.
884
        self.assertRaises(KnitCorrupt, list,
7143.15.2 by Jelmer Vernooij
Run autopep8.
885
                          knit._read_records_iter(records))
2329.1.1 by John Arbash Meinel
Update _KnitData parser to raise more helpful errors when it detects corruption.
886
3350.6.4 by Robert Collins
First cut at pluralised VersionedFiles. Some rather massive API incompatabilities, primarily because of the difficulty of coherence among competing stores.
887
        # read_records_iter_raw detects mismatches in the header
6729.7.2 by Jelmer Vernooij
Finish move.
888
        self.assertRaises(KnitCorrupt, list,
7143.15.2 by Jelmer Vernooij
Run autopep8.
889
                          knit._read_records_iter_raw(records))
2329.1.1 by John Arbash Meinel
Update _KnitData parser to raise more helpful errors when it detects corruption.
890
891
    def test_uncompressed_data(self):
6985 by Jelmer Vernooij
Merge lp:~jelmer/brz/python3-weave-fmt.
892
        sha1sum = osutils.sha_string(b'foo\nbar\n')
893
        txt = (b'version rev-id-1 2 %s\n'
894
               b'foo\n'
895
               b'bar\n'
896
               b'end rev-id-1\n'
2329.1.1 by John Arbash Meinel
Update _KnitData parser to raise more helpful errors when it detects corruption.
897
               % (sha1sum,))
898
        transport = MockTransport([txt])
3350.6.4 by Robert Collins
First cut at pluralised VersionedFiles. Some rather massive API incompatabilities, primarily because of the difficulty of coherence among competing stores.
899
        access = _KnitKeyAccess(transport, ConstantMapper('filename'))
900
        knit = KnitVersionedFiles(None, access)
6985 by Jelmer Vernooij
Merge lp:~jelmer/brz/python3-weave-fmt.
901
        records = [((b'rev-id-1',), ((b'rev-id-1',), 0, len(txt)))]
2329.1.1 by John Arbash Meinel
Update _KnitData parser to raise more helpful errors when it detects corruption.
902
903
        # We don't have valid gzip data ==> corrupt
6729.7.2 by Jelmer Vernooij
Finish move.
904
        self.assertRaises(KnitCorrupt, list,
7143.15.2 by Jelmer Vernooij
Run autopep8.
905
                          knit._read_records_iter(records))
2329.1.1 by John Arbash Meinel
Update _KnitData parser to raise more helpful errors when it detects corruption.
906
907
        # read_records_iter_raw will notice the bad data
6729.7.2 by Jelmer Vernooij
Finish move.
908
        self.assertRaises(KnitCorrupt, list,
7143.15.2 by Jelmer Vernooij
Run autopep8.
909
                          knit._read_records_iter_raw(records))
2329.1.1 by John Arbash Meinel
Update _KnitData parser to raise more helpful errors when it detects corruption.
910
911
    def test_corrupted_data(self):
6985 by Jelmer Vernooij
Merge lp:~jelmer/brz/python3-weave-fmt.
912
        sha1sum = osutils.sha_string(b'foo\nbar\n')
913
        gz_txt = self.create_gz_content(b'version rev-id-1 2 %s\n'
914
                                        b'foo\n'
915
                                        b'bar\n'
916
                                        b'end rev-id-1\n'
2329.1.1 by John Arbash Meinel
Update _KnitData parser to raise more helpful errors when it detects corruption.
917
                                        % (sha1sum,))
918
        # Change 2 bytes in the middle to \xff
6985 by Jelmer Vernooij
Merge lp:~jelmer/brz/python3-weave-fmt.
919
        gz_txt = gz_txt[:10] + b'\xff\xff' + gz_txt[12:]
2329.1.1 by John Arbash Meinel
Update _KnitData parser to raise more helpful errors when it detects corruption.
920
        transport = MockTransport([gz_txt])
3350.6.4 by Robert Collins
First cut at pluralised VersionedFiles. Some rather massive API incompatabilities, primarily because of the difficulty of coherence among competing stores.
921
        access = _KnitKeyAccess(transport, ConstantMapper('filename'))
922
        knit = KnitVersionedFiles(None, access)
6985 by Jelmer Vernooij
Merge lp:~jelmer/brz/python3-weave-fmt.
923
        records = [((b'rev-id-1',), ((b'rev-id-1',), 0, len(gz_txt)))]
6729.7.2 by Jelmer Vernooij
Finish move.
924
        self.assertRaises(KnitCorrupt, list,
7143.15.2 by Jelmer Vernooij
Run autopep8.
925
                          knit._read_records_iter(records))
3350.6.4 by Robert Collins
First cut at pluralised VersionedFiles. Some rather massive API incompatabilities, primarily because of the difficulty of coherence among competing stores.
926
        # read_records_iter_raw will barf on bad gz data
6729.7.2 by Jelmer Vernooij
Finish move.
927
        self.assertRaises(KnitCorrupt, list,
7143.15.2 by Jelmer Vernooij
Run autopep8.
928
                          knit._read_records_iter_raw(records))
2329.1.1 by John Arbash Meinel
Update _KnitData parser to raise more helpful errors when it detects corruption.
929
930
2158.3.1 by Dmitry Vasiliev
KnitIndex tests/fixes/optimizations
931
class LowLevelKnitIndexTests(TestCase):
932
7027.1.2 by Martin
Fixup low level knit tests for Python 3
933
    @property
934
    def _load_data(self):
6670.4.3 by Jelmer Vernooij
Fix more imports.
935
        from ..bzr._knit_load_data_py import _load_data_py
7027.1.2 by Martin
Fixup low level knit tests for Python 3
936
        return _load_data_py
937
938
    def get_knit_index(self, transport, name, mode):
939
        mapper = ConstantMapper(name)
940
        self.overrideAttr(knit, '_load_data', self._load_data)
7143.15.2 by Jelmer Vernooij
Run autopep8.
941
7143.15.5 by Jelmer Vernooij
More PEP8 fixes.
942
        def allow_writes():
943
            return 'w' in mode
7027.1.2 by Martin
Fixup low level knit tests for Python 3
944
        return _KndxIndex(transport, mapper, lambda: None, allow_writes, lambda: True)
2158.3.1 by Dmitry Vasiliev
KnitIndex tests/fixes/optimizations
945
946
    def test_create_file(self):
947
        transport = MockTransport()
3350.6.4 by Robert Collins
First cut at pluralised VersionedFiles. Some rather massive API incompatabilities, primarily because of the difficulty of coherence among competing stores.
948
        index = self.get_knit_index(transport, "filename", "w")
949
        index.keys()
950
        call = transport.calls.pop(0)
6621.22.2 by Martin
Use BytesIO or StringIO from bzrlib.sixish
951
        # call[1][1] is a BytesIO - we can't test it by simple equality.
3350.6.4 by Robert Collins
First cut at pluralised VersionedFiles. Some rather massive API incompatabilities, primarily because of the difficulty of coherence among competing stores.
952
        self.assertEqual('put_file_non_atomic', call[0])
953
        self.assertEqual('filename.kndx', call[1][0])
954
        # With no history, _KndxIndex writes a new index:
955
        self.assertEqual(_KndxIndex.HEADER,
7143.15.2 by Jelmer Vernooij
Run autopep8.
956
                         call[1][1].getvalue())
3350.6.4 by Robert Collins
First cut at pluralised VersionedFiles. Some rather massive API incompatabilities, primarily because of the difficulty of coherence among competing stores.
957
        self.assertEqual({'create_parent_dir': True}, call[2])
2158.3.1 by Dmitry Vasiliev
KnitIndex tests/fixes/optimizations
958
959
    def test_read_utf8_version_id(self):
2249.5.12 by John Arbash Meinel
Change the APIs for VersionedFile, Store, and some of Repository into utf-8
960
        unicode_revision_id = u"version-\N{CYRILLIC CAPITAL LETTER A}"
961
        utf8_revision_id = unicode_revision_id.encode('utf-8')
2158.3.1 by Dmitry Vasiliev
KnitIndex tests/fixes/optimizations
962
        transport = MockTransport([
3350.6.4 by Robert Collins
First cut at pluralised VersionedFiles. Some rather massive API incompatabilities, primarily because of the difficulty of coherence among competing stores.
963
            _KndxIndex.HEADER,
6973.14.2 by Jelmer Vernooij
Fix some knit tests.
964
            b'%s option 0 1 :' % (utf8_revision_id,)
2158.3.1 by Dmitry Vasiliev
KnitIndex tests/fixes/optimizations
965
            ])
2484.1.1 by John Arbash Meinel
Add an initial function to read knit indexes in pyrex.
966
        index = self.get_knit_index(transport, "filename", "r")
3350.6.4 by Robert Collins
First cut at pluralised VersionedFiles. Some rather massive API incompatabilities, primarily because of the difficulty of coherence among competing stores.
967
        # _KndxIndex is a private class, and deals in utf8 revision_ids, not
2249.5.12 by John Arbash Meinel
Change the APIs for VersionedFile, Store, and some of Repository into utf-8
968
        # Unicode revision_ids.
7143.15.2 by Jelmer Vernooij
Run autopep8.
969
        self.assertEqual({(utf8_revision_id,): ()},
970
                         index.get_parent_map(index.keys()))
3350.6.4 by Robert Collins
First cut at pluralised VersionedFiles. Some rather massive API incompatabilities, primarily because of the difficulty of coherence among competing stores.
971
        self.assertFalse((unicode_revision_id,) in index.keys())
2158.3.1 by Dmitry Vasiliev
KnitIndex tests/fixes/optimizations
972
973
    def test_read_utf8_parents(self):
2249.5.12 by John Arbash Meinel
Change the APIs for VersionedFile, Store, and some of Repository into utf-8
974
        unicode_revision_id = u"version-\N{CYRILLIC CAPITAL LETTER A}"
975
        utf8_revision_id = unicode_revision_id.encode('utf-8')
2158.3.1 by Dmitry Vasiliev
KnitIndex tests/fixes/optimizations
976
        transport = MockTransport([
3350.6.4 by Robert Collins
First cut at pluralised VersionedFiles. Some rather massive API incompatabilities, primarily because of the difficulty of coherence among competing stores.
977
            _KndxIndex.HEADER,
6985 by Jelmer Vernooij
Merge lp:~jelmer/brz/python3-weave-fmt.
978
            b"version option 0 1 .%s :" % (utf8_revision_id,)
2158.3.1 by Dmitry Vasiliev
KnitIndex tests/fixes/optimizations
979
            ])
2484.1.1 by John Arbash Meinel
Add an initial function to read knit indexes in pyrex.
980
        index = self.get_knit_index(transport, "filename", "r")
7027.1.2 by Martin
Fixup low level knit tests for Python 3
981
        self.assertEqual({(b"version",): ((utf8_revision_id,),)},
7143.15.2 by Jelmer Vernooij
Run autopep8.
982
                         index.get_parent_map(index.keys()))
2158.3.1 by Dmitry Vasiliev
KnitIndex tests/fixes/optimizations
983
984
    def test_read_ignore_corrupted_lines(self):
985
        transport = MockTransport([
3350.6.4 by Robert Collins
First cut at pluralised VersionedFiles. Some rather massive API incompatabilities, primarily because of the difficulty of coherence among competing stores.
986
            _KndxIndex.HEADER,
6985 by Jelmer Vernooij
Merge lp:~jelmer/brz/python3-weave-fmt.
987
            b"corrupted",
988
            b"corrupted options 0 1 .b .c ",
989
            b"version options 0 1 :"
2158.3.1 by Dmitry Vasiliev
KnitIndex tests/fixes/optimizations
990
            ])
2484.1.1 by John Arbash Meinel
Add an initial function to read knit indexes in pyrex.
991
        index = self.get_knit_index(transport, "filename", "r")
3350.6.4 by Robert Collins
First cut at pluralised VersionedFiles. Some rather massive API incompatabilities, primarily because of the difficulty of coherence among competing stores.
992
        self.assertEqual(1, len(index.keys()))
7027.1.2 by Martin
Fixup low level knit tests for Python 3
993
        self.assertEqual({(b"version",)}, index.keys())
2158.3.1 by Dmitry Vasiliev
KnitIndex tests/fixes/optimizations
994
995
    def test_read_corrupted_header(self):
6985 by Jelmer Vernooij
Merge lp:~jelmer/brz/python3-weave-fmt.
996
        transport = MockTransport([b'not a bzr knit index header\n'])
3350.6.4 by Robert Collins
First cut at pluralised VersionedFiles. Some rather massive API incompatabilities, primarily because of the difficulty of coherence among competing stores.
997
        index = self.get_knit_index(transport, "filename", "r")
998
        self.assertRaises(KnitHeaderError, index.keys)
2158.3.1 by Dmitry Vasiliev
KnitIndex tests/fixes/optimizations
999
1000
    def test_read_duplicate_entries(self):
1001
        transport = MockTransport([
3350.6.4 by Robert Collins
First cut at pluralised VersionedFiles. Some rather massive API incompatabilities, primarily because of the difficulty of coherence among competing stores.
1002
            _KndxIndex.HEADER,
6985 by Jelmer Vernooij
Merge lp:~jelmer/brz/python3-weave-fmt.
1003
            b"parent options 0 1 :",
1004
            b"version options1 0 1 0 :",
1005
            b"version options2 1 2 .other :",
1006
            b"version options3 3 4 0 .other :"
2158.3.1 by Dmitry Vasiliev
KnitIndex tests/fixes/optimizations
1007
            ])
2484.1.1 by John Arbash Meinel
Add an initial function to read knit indexes in pyrex.
1008
        index = self.get_knit_index(transport, "filename", "r")
3350.6.4 by Robert Collins
First cut at pluralised VersionedFiles. Some rather massive API incompatabilities, primarily because of the difficulty of coherence among competing stores.
1009
        self.assertEqual(2, len(index.keys()))
2592.3.8 by Robert Collins
Remove unneeded pulib method lookup on private class _KnitIndex.
1010
        # check that the index used is the first one written. (Specific
1011
        # to KnitIndex style indices.
7027.1.2 by Martin
Fixup low level knit tests for Python 3
1012
        self.assertEqual(b"1", index._dictionary_compress([(b"version",)]))
7143.15.2 by Jelmer Vernooij
Run autopep8.
1013
        self.assertEqual(((b"version",), 3, 4),
1014
                         index.get_position((b"version",)))
7027.1.2 by Martin
Fixup low level knit tests for Python 3
1015
        self.assertEqual([b"options3"], index.get_options((b"version",)))
1016
        self.assertEqual({(b"version",): ((b"parent",), (b"other",))},
7143.15.2 by Jelmer Vernooij
Run autopep8.
1017
                         index.get_parent_map([(b"version",)]))
2158.3.1 by Dmitry Vasiliev
KnitIndex tests/fixes/optimizations
1018
1019
    def test_read_compressed_parents(self):
1020
        transport = MockTransport([
3350.6.4 by Robert Collins
First cut at pluralised VersionedFiles. Some rather massive API incompatabilities, primarily because of the difficulty of coherence among competing stores.
1021
            _KndxIndex.HEADER,
6985 by Jelmer Vernooij
Merge lp:~jelmer/brz/python3-weave-fmt.
1022
            b"a option 0 1 :",
1023
            b"b option 0 1 0 :",
1024
            b"c option 0 1 1 0 :",
2158.3.1 by Dmitry Vasiliev
KnitIndex tests/fixes/optimizations
1025
            ])
2484.1.1 by John Arbash Meinel
Add an initial function to read knit indexes in pyrex.
1026
        index = self.get_knit_index(transport, "filename", "r")
7143.15.2 by Jelmer Vernooij
Run autopep8.
1027
        self.assertEqual({(b"b",): ((b"a",),), (b"c",): ((b"b",), (b"a",))},
1028
                         index.get_parent_map([(b"b",), (b"c",)]))
2158.3.1 by Dmitry Vasiliev
KnitIndex tests/fixes/optimizations
1029
1030
    def test_write_utf8_version_id(self):
2249.5.12 by John Arbash Meinel
Change the APIs for VersionedFile, Store, and some of Repository into utf-8
1031
        unicode_revision_id = u"version-\N{CYRILLIC CAPITAL LETTER A}"
1032
        utf8_revision_id = unicode_revision_id.encode('utf-8')
2158.3.1 by Dmitry Vasiliev
KnitIndex tests/fixes/optimizations
1033
        transport = MockTransport([
3350.6.4 by Robert Collins
First cut at pluralised VersionedFiles. Some rather massive API incompatabilities, primarily because of the difficulty of coherence among competing stores.
1034
            _KndxIndex.HEADER
2158.3.1 by Dmitry Vasiliev
KnitIndex tests/fixes/optimizations
1035
            ])
2484.1.1 by John Arbash Meinel
Add an initial function to read knit indexes in pyrex.
1036
        index = self.get_knit_index(transport, "filename", "r")
3350.6.4 by Robert Collins
First cut at pluralised VersionedFiles. Some rather massive API incompatabilities, primarily because of the difficulty of coherence among competing stores.
1037
        index.add_records([
6973.14.2 by Jelmer Vernooij
Fix some knit tests.
1038
            ((utf8_revision_id,), [b"option"], ((utf8_revision_id,), 0, 1), [])])
3350.6.4 by Robert Collins
First cut at pluralised VersionedFiles. Some rather massive API incompatabilities, primarily because of the difficulty of coherence among competing stores.
1039
        call = transport.calls.pop(0)
6621.22.2 by Martin
Use BytesIO or StringIO from bzrlib.sixish
1040
        # call[1][1] is a BytesIO - we can't test it by simple equality.
3350.6.4 by Robert Collins
First cut at pluralised VersionedFiles. Some rather massive API incompatabilities, primarily because of the difficulty of coherence among competing stores.
1041
        self.assertEqual('put_file_non_atomic', call[0])
1042
        self.assertEqual('filename.kndx', call[1][0])
1043
        # With no history, _KndxIndex writes a new index:
1044
        self.assertEqual(_KndxIndex.HEADER +
7143.15.2 by Jelmer Vernooij
Run autopep8.
1045
                         b"\n%s option 0 1  :" % (utf8_revision_id,),
1046
                         call[1][1].getvalue())
3350.6.4 by Robert Collins
First cut at pluralised VersionedFiles. Some rather massive API incompatabilities, primarily because of the difficulty of coherence among competing stores.
1047
        self.assertEqual({'create_parent_dir': True}, call[2])
2158.3.1 by Dmitry Vasiliev
KnitIndex tests/fixes/optimizations
1048
1049
    def test_write_utf8_parents(self):
2249.5.12 by John Arbash Meinel
Change the APIs for VersionedFile, Store, and some of Repository into utf-8
1050
        unicode_revision_id = u"version-\N{CYRILLIC CAPITAL LETTER A}"
1051
        utf8_revision_id = unicode_revision_id.encode('utf-8')
2158.3.1 by Dmitry Vasiliev
KnitIndex tests/fixes/optimizations
1052
        transport = MockTransport([
3350.6.4 by Robert Collins
First cut at pluralised VersionedFiles. Some rather massive API incompatabilities, primarily because of the difficulty of coherence among competing stores.
1053
            _KndxIndex.HEADER
1054
            ])
1055
        index = self.get_knit_index(transport, "filename", "r")
1056
        index.add_records([
6973.14.2 by Jelmer Vernooij
Fix some knit tests.
1057
            ((b"version",), [b"option"], ((b"version",), 0, 1), [(utf8_revision_id,)])])
3350.6.4 by Robert Collins
First cut at pluralised VersionedFiles. Some rather massive API incompatabilities, primarily because of the difficulty of coherence among competing stores.
1058
        call = transport.calls.pop(0)
6621.22.2 by Martin
Use BytesIO or StringIO from bzrlib.sixish
1059
        # call[1][1] is a BytesIO - we can't test it by simple equality.
3350.6.4 by Robert Collins
First cut at pluralised VersionedFiles. Some rather massive API incompatabilities, primarily because of the difficulty of coherence among competing stores.
1060
        self.assertEqual('put_file_non_atomic', call[0])
1061
        self.assertEqual('filename.kndx', call[1][0])
1062
        # With no history, _KndxIndex writes a new index:
1063
        self.assertEqual(_KndxIndex.HEADER +
7143.15.2 by Jelmer Vernooij
Run autopep8.
1064
                         b"\nversion option 0 1 .%s :" % (utf8_revision_id,),
1065
                         call[1][1].getvalue())
3350.6.4 by Robert Collins
First cut at pluralised VersionedFiles. Some rather massive API incompatabilities, primarily because of the difficulty of coherence among competing stores.
1066
        self.assertEqual({'create_parent_dir': True}, call[2])
1067
1068
    def test_keys(self):
1069
        transport = MockTransport([
1070
            _KndxIndex.HEADER
1071
            ])
1072
        index = self.get_knit_index(transport, "filename", "r")
1073
1074
        self.assertEqual(set(), index.keys())
1075
6973.14.2 by Jelmer Vernooij
Fix some knit tests.
1076
        index.add_records([((b"a",), [b"option"], ((b"a",), 0, 1), [])])
1077
        self.assertEqual({(b"a",)}, index.keys())
1078
1079
        index.add_records([((b"a",), [b"option"], ((b"a",), 0, 1), [])])
1080
        self.assertEqual({(b"a",)}, index.keys())
1081
1082
        index.add_records([((b"b",), [b"option"], ((b"b",), 0, 1), [])])
1083
        self.assertEqual({(b"a",), (b"b",)}, index.keys())
3350.6.4 by Robert Collins
First cut at pluralised VersionedFiles. Some rather massive API incompatabilities, primarily because of the difficulty of coherence among competing stores.
1084
1085
    def add_a_b(self, index, random_id=None):
1086
        kwargs = {}
1087
        if random_id is not None:
1088
            kwargs["random_id"] = random_id
1089
        index.add_records([
6973.14.2 by Jelmer Vernooij
Fix some knit tests.
1090
            ((b"a",), [b"option"], ((b"a",), 0, 1), [(b"b",)]),
1091
            ((b"a",), [b"opt"], ((b"a",), 1, 2), [(b"c",)]),
1092
            ((b"b",), [b"option"], ((b"b",), 2, 3), [(b"a",)])
3350.6.4 by Robert Collins
First cut at pluralised VersionedFiles. Some rather massive API incompatabilities, primarily because of the difficulty of coherence among competing stores.
1093
            ], **kwargs)
1094
1095
    def assertIndexIsAB(self, index):
1096
        self.assertEqual({
6973.14.2 by Jelmer Vernooij
Fix some knit tests.
1097
            (b'a',): ((b'c',),),
1098
            (b'b',): ((b'a',),),
3350.6.4 by Robert Collins
First cut at pluralised VersionedFiles. Some rather massive API incompatabilities, primarily because of the difficulty of coherence among competing stores.
1099
            },
1100
            index.get_parent_map(index.keys()))
6973.14.2 by Jelmer Vernooij
Fix some knit tests.
1101
        self.assertEqual(((b"a",), 1, 2), index.get_position((b"a",)))
1102
        self.assertEqual(((b"b",), 2, 3), index.get_position((b"b",)))
1103
        self.assertEqual([b"opt"], index.get_options((b"a",)))
3350.6.4 by Robert Collins
First cut at pluralised VersionedFiles. Some rather massive API incompatabilities, primarily because of the difficulty of coherence among competing stores.
1104
1105
    def test_add_versions(self):
1106
        transport = MockTransport([
1107
            _KndxIndex.HEADER
1108
            ])
1109
        index = self.get_knit_index(transport, "filename", "r")
1110
1111
        self.add_a_b(index)
1112
        call = transport.calls.pop(0)
6621.22.2 by Martin
Use BytesIO or StringIO from bzrlib.sixish
1113
        # call[1][1] is a BytesIO - we can't test it by simple equality.
3350.6.4 by Robert Collins
First cut at pluralised VersionedFiles. Some rather massive API incompatabilities, primarily because of the difficulty of coherence among competing stores.
1114
        self.assertEqual('put_file_non_atomic', call[0])
1115
        self.assertEqual('filename.kndx', call[1][0])
1116
        # With no history, _KndxIndex writes a new index:
2158.3.1 by Dmitry Vasiliev
KnitIndex tests/fixes/optimizations
1117
        self.assertEqual(
3350.6.4 by Robert Collins
First cut at pluralised VersionedFiles. Some rather massive API incompatabilities, primarily because of the difficulty of coherence among competing stores.
1118
            _KndxIndex.HEADER +
6985 by Jelmer Vernooij
Merge lp:~jelmer/brz/python3-weave-fmt.
1119
            b"\na option 0 1 .b :"
1120
            b"\na opt 1 2 .c :"
1121
            b"\nb option 2 3 0 :",
3350.6.4 by Robert Collins
First cut at pluralised VersionedFiles. Some rather massive API incompatabilities, primarily because of the difficulty of coherence among competing stores.
1122
            call[1][1].getvalue())
1123
        self.assertEqual({'create_parent_dir': True}, call[2])
1124
        self.assertIndexIsAB(index)
2158.3.1 by Dmitry Vasiliev
KnitIndex tests/fixes/optimizations
1125
2841.2.1 by Robert Collins
* Commit no longer checks for new text keys during insertion when the
1126
    def test_add_versions_random_id_is_accepted(self):
1127
        transport = MockTransport([
3350.6.4 by Robert Collins
First cut at pluralised VersionedFiles. Some rather massive API incompatabilities, primarily because of the difficulty of coherence among competing stores.
1128
            _KndxIndex.HEADER
2841.2.1 by Robert Collins
* Commit no longer checks for new text keys during insertion when the
1129
            ])
1130
        index = self.get_knit_index(transport, "filename", "r")
3350.6.4 by Robert Collins
First cut at pluralised VersionedFiles. Some rather massive API incompatabilities, primarily because of the difficulty of coherence among competing stores.
1131
        self.add_a_b(index, random_id=True)
2841.2.1 by Robert Collins
* Commit no longer checks for new text keys during insertion when the
1132
2158.3.1 by Dmitry Vasiliev
KnitIndex tests/fixes/optimizations
1133
    def test_delay_create_and_add_versions(self):
1134
        transport = MockTransport()
1135
3350.6.4 by Robert Collins
First cut at pluralised VersionedFiles. Some rather massive API incompatabilities, primarily because of the difficulty of coherence among competing stores.
1136
        index = self.get_knit_index(transport, "filename", "w")
1137
        # dir_mode=0777)
2158.3.1 by Dmitry Vasiliev
KnitIndex tests/fixes/optimizations
1138
        self.assertEqual([], transport.calls)
3350.6.4 by Robert Collins
First cut at pluralised VersionedFiles. Some rather massive API incompatabilities, primarily because of the difficulty of coherence among competing stores.
1139
        self.add_a_b(index)
7143.15.2 by Jelmer Vernooij
Run autopep8.
1140
        # self.assertEqual(
1141
        # [    {"dir_mode": 0777, "create_parent_dir": True, "mode": "wb"},
3350.6.4 by Robert Collins
First cut at pluralised VersionedFiles. Some rather massive API incompatabilities, primarily because of the difficulty of coherence among competing stores.
1142
        #    kwargs)
1143
        # Two calls: one during which we load the existing index (and when its
1144
        # missing create it), then a second where we write the contents out.
1145
        self.assertEqual(2, len(transport.calls))
1146
        call = transport.calls.pop(0)
1147
        self.assertEqual('put_file_non_atomic', call[0])
1148
        self.assertEqual('filename.kndx', call[1][0])
1149
        # With no history, _KndxIndex writes a new index:
1150
        self.assertEqual(_KndxIndex.HEADER, call[1][1].getvalue())
1151
        self.assertEqual({'create_parent_dir': True}, call[2])
1152
        call = transport.calls.pop(0)
6621.22.2 by Martin
Use BytesIO or StringIO from bzrlib.sixish
1153
        # call[1][1] is a BytesIO - we can't test it by simple equality.
3350.6.4 by Robert Collins
First cut at pluralised VersionedFiles. Some rather massive API incompatabilities, primarily because of the difficulty of coherence among competing stores.
1154
        self.assertEqual('put_file_non_atomic', call[0])
1155
        self.assertEqual('filename.kndx', call[1][0])
1156
        # With no history, _KndxIndex writes a new index:
1157
        self.assertEqual(
1158
            _KndxIndex.HEADER +
6985 by Jelmer Vernooij
Merge lp:~jelmer/brz/python3-weave-fmt.
1159
            b"\na option 0 1 .b :"
1160
            b"\na opt 1 2 .c :"
1161
            b"\nb option 2 3 0 :",
3350.6.4 by Robert Collins
First cut at pluralised VersionedFiles. Some rather massive API incompatabilities, primarily because of the difficulty of coherence among competing stores.
1162
            call[1][1].getvalue())
1163
        self.assertEqual({'create_parent_dir': True}, call[2])
2158.3.1 by Dmitry Vasiliev
KnitIndex tests/fixes/optimizations
1164
4039.3.5 by John Arbash Meinel
Add direct tests for _get_total_build_size.
1165
    def assertTotalBuildSize(self, size, keys, positions):
1166
        self.assertEqual(size,
1167
                         knit._get_total_build_size(None, keys, positions))
1168
1169
    def test__get_total_build_size(self):
1170
        positions = {
7078.6.1 by Jelmer Vernooij
Fix corrupt knit handling on Python 3.
1171
            (b'a',): (('fulltext', False), ((b'a',), 0, 100), None),
1172
            (b'b',): (('line-delta', False), ((b'b',), 100, 21), (b'a',)),
1173
            (b'c',): (('line-delta', False), ((b'c',), 121, 35), (b'b',)),
1174
            (b'd',): (('line-delta', False), ((b'd',), 156, 12), (b'b',)),
4039.3.5 by John Arbash Meinel
Add direct tests for _get_total_build_size.
1175
            }
6973.14.2 by Jelmer Vernooij
Fix some knit tests.
1176
        self.assertTotalBuildSize(100, [(b'a',)], positions)
1177
        self.assertTotalBuildSize(121, [(b'b',)], positions)
4039.3.5 by John Arbash Meinel
Add direct tests for _get_total_build_size.
1178
        # c needs both a & b
6973.14.2 by Jelmer Vernooij
Fix some knit tests.
1179
        self.assertTotalBuildSize(156, [(b'c',)], positions)
4039.3.5 by John Arbash Meinel
Add direct tests for _get_total_build_size.
1180
        # we shouldn't count 'b' twice
6973.14.2 by Jelmer Vernooij
Fix some knit tests.
1181
        self.assertTotalBuildSize(156, [(b'b',), (b'c',)], positions)
1182
        self.assertTotalBuildSize(133, [(b'd',)], positions)
1183
        self.assertTotalBuildSize(168, [(b'c',), (b'd',)], positions)
4039.3.5 by John Arbash Meinel
Add direct tests for _get_total_build_size.
1184
2158.3.1 by Dmitry Vasiliev
KnitIndex tests/fixes/optimizations
1185
    def test_get_position(self):
1186
        transport = MockTransport([
3350.6.4 by Robert Collins
First cut at pluralised VersionedFiles. Some rather massive API incompatabilities, primarily because of the difficulty of coherence among competing stores.
1187
            _KndxIndex.HEADER,
6985 by Jelmer Vernooij
Merge lp:~jelmer/brz/python3-weave-fmt.
1188
            b"a option 0 1 :",
1189
            b"b option 1 2 :"
2158.3.1 by Dmitry Vasiliev
KnitIndex tests/fixes/optimizations
1190
            ])
2484.1.1 by John Arbash Meinel
Add an initial function to read knit indexes in pyrex.
1191
        index = self.get_knit_index(transport, "filename", "r")
2158.3.1 by Dmitry Vasiliev
KnitIndex tests/fixes/optimizations
1192
6973.14.2 by Jelmer Vernooij
Fix some knit tests.
1193
        self.assertEqual(((b"a",), 0, 1), index.get_position((b"a",)))
1194
        self.assertEqual(((b"b",), 1, 2), index.get_position((b"b",)))
2158.3.1 by Dmitry Vasiliev
KnitIndex tests/fixes/optimizations
1195
1196
    def test_get_method(self):
1197
        transport = MockTransport([
3350.6.4 by Robert Collins
First cut at pluralised VersionedFiles. Some rather massive API incompatabilities, primarily because of the difficulty of coherence among competing stores.
1198
            _KndxIndex.HEADER,
6985 by Jelmer Vernooij
Merge lp:~jelmer/brz/python3-weave-fmt.
1199
            b"a fulltext,unknown 0 1 :",
1200
            b"b unknown,line-delta 1 2 :",
1201
            b"c bad 3 4 :"
2158.3.1 by Dmitry Vasiliev
KnitIndex tests/fixes/optimizations
1202
            ])
2484.1.1 by John Arbash Meinel
Add an initial function to read knit indexes in pyrex.
1203
        index = self.get_knit_index(transport, "filename", "r")
2158.3.1 by Dmitry Vasiliev
KnitIndex tests/fixes/optimizations
1204
7027.1.2 by Martin
Fixup low level knit tests for Python 3
1205
        self.assertEqual("fulltext", index.get_method(b"a"))
1206
        self.assertEqual("line-delta", index.get_method(b"b"))
6973.14.2 by Jelmer Vernooij
Fix some knit tests.
1207
        self.assertRaises(knit.KnitIndexUnknownMethod, index.get_method, b"c")
2158.3.1 by Dmitry Vasiliev
KnitIndex tests/fixes/optimizations
1208
1209
    def test_get_options(self):
1210
        transport = MockTransport([
3350.6.4 by Robert Collins
First cut at pluralised VersionedFiles. Some rather massive API incompatabilities, primarily because of the difficulty of coherence among competing stores.
1211
            _KndxIndex.HEADER,
6985 by Jelmer Vernooij
Merge lp:~jelmer/brz/python3-weave-fmt.
1212
            b"a opt1 0 1 :",
1213
            b"b opt2,opt3 1 2 :"
2158.3.1 by Dmitry Vasiliev
KnitIndex tests/fixes/optimizations
1214
            ])
2484.1.1 by John Arbash Meinel
Add an initial function to read knit indexes in pyrex.
1215
        index = self.get_knit_index(transport, "filename", "r")
2158.3.1 by Dmitry Vasiliev
KnitIndex tests/fixes/optimizations
1216
6973.14.2 by Jelmer Vernooij
Fix some knit tests.
1217
        self.assertEqual([b"opt1"], index.get_options(b"a"))
1218
        self.assertEqual([b"opt2", b"opt3"], index.get_options(b"b"))
2158.3.1 by Dmitry Vasiliev
KnitIndex tests/fixes/optimizations
1219
3287.5.6 by Robert Collins
Remove _KnitIndex.get_parents.
1220
    def test_get_parent_map(self):
2158.3.1 by Dmitry Vasiliev
KnitIndex tests/fixes/optimizations
1221
        transport = MockTransport([
3350.6.4 by Robert Collins
First cut at pluralised VersionedFiles. Some rather massive API incompatabilities, primarily because of the difficulty of coherence among competing stores.
1222
            _KndxIndex.HEADER,
6985 by Jelmer Vernooij
Merge lp:~jelmer/brz/python3-weave-fmt.
1223
            b"a option 0 1 :",
1224
            b"b option 1 2 0 .c :",
1225
            b"c option 1 2 1 0 .e :"
2158.3.1 by Dmitry Vasiliev
KnitIndex tests/fixes/optimizations
1226
            ])
2484.1.1 by John Arbash Meinel
Add an initial function to read knit indexes in pyrex.
1227
        index = self.get_knit_index(transport, "filename", "r")
2158.3.1 by Dmitry Vasiliev
KnitIndex tests/fixes/optimizations
1228
3287.5.6 by Robert Collins
Remove _KnitIndex.get_parents.
1229
        self.assertEqual({
6985 by Jelmer Vernooij
Merge lp:~jelmer/brz/python3-weave-fmt.
1230
            (b"a",): (),
1231
            (b"b",): ((b"a",), (b"c",)),
1232
            (b"c",): ((b"b",), (b"a",), (b"e",)),
3350.6.4 by Robert Collins
First cut at pluralised VersionedFiles. Some rather massive API incompatabilities, primarily because of the difficulty of coherence among competing stores.
1233
            }, index.get_parent_map(index.keys()))
2158.3.1 by Dmitry Vasiliev
KnitIndex tests/fixes/optimizations
1234
2484.1.13 by John Arbash Meinel
Add a test that KnitCorrupt is raised when parent strings are invalid.
1235
    def test_impossible_parent(self):
1236
        """Test we get KnitCorrupt if the parent couldn't possibly exist."""
1237
        transport = MockTransport([
3350.6.4 by Robert Collins
First cut at pluralised VersionedFiles. Some rather massive API incompatabilities, primarily because of the difficulty of coherence among competing stores.
1238
            _KndxIndex.HEADER,
6985 by Jelmer Vernooij
Merge lp:~jelmer/brz/python3-weave-fmt.
1239
            b"a option 0 1 :",
1240
            b"b option 0 1 4 :"  # We don't have a 4th record
2484.1.13 by John Arbash Meinel
Add a test that KnitCorrupt is raised when parent strings are invalid.
1241
            ])
3350.6.4 by Robert Collins
First cut at pluralised VersionedFiles. Some rather massive API incompatabilities, primarily because of the difficulty of coherence among competing stores.
1242
        index = self.get_knit_index(transport, 'filename', 'r')
6729.7.2 by Jelmer Vernooij
Finish move.
1243
        self.assertRaises(KnitCorrupt, index.keys)
2484.1.13 by John Arbash Meinel
Add a test that KnitCorrupt is raised when parent strings are invalid.
1244
1245
    def test_corrupted_parent(self):
1246
        transport = MockTransport([
3350.6.4 by Robert Collins
First cut at pluralised VersionedFiles. Some rather massive API incompatabilities, primarily because of the difficulty of coherence among competing stores.
1247
            _KndxIndex.HEADER,
6985 by Jelmer Vernooij
Merge lp:~jelmer/brz/python3-weave-fmt.
1248
            b"a option 0 1 :",
1249
            b"b option 0 1 :",
7143.15.2 by Jelmer Vernooij
Run autopep8.
1250
            b"c option 0 1 1v :",  # Can't have a parent of '1v'
2484.1.13 by John Arbash Meinel
Add a test that KnitCorrupt is raised when parent strings are invalid.
1251
            ])
3350.6.4 by Robert Collins
First cut at pluralised VersionedFiles. Some rather massive API incompatabilities, primarily because of the difficulty of coherence among competing stores.
1252
        index = self.get_knit_index(transport, 'filename', 'r')
6729.7.2 by Jelmer Vernooij
Finish move.
1253
        self.assertRaises(KnitCorrupt, index.keys)
2484.1.13 by John Arbash Meinel
Add a test that KnitCorrupt is raised when parent strings are invalid.
1254
1255
    def test_corrupted_parent_in_list(self):
1256
        transport = MockTransport([
3350.6.4 by Robert Collins
First cut at pluralised VersionedFiles. Some rather massive API incompatabilities, primarily because of the difficulty of coherence among competing stores.
1257
            _KndxIndex.HEADER,
6985 by Jelmer Vernooij
Merge lp:~jelmer/brz/python3-weave-fmt.
1258
            b"a option 0 1 :",
1259
            b"b option 0 1 :",
7143.15.2 by Jelmer Vernooij
Run autopep8.
1260
            b"c option 0 1 1 v :",  # Can't have a parent of 'v'
2484.1.13 by John Arbash Meinel
Add a test that KnitCorrupt is raised when parent strings are invalid.
1261
            ])
3350.6.4 by Robert Collins
First cut at pluralised VersionedFiles. Some rather massive API incompatabilities, primarily because of the difficulty of coherence among competing stores.
1262
        index = self.get_knit_index(transport, 'filename', 'r')
6729.7.2 by Jelmer Vernooij
Finish move.
1263
        self.assertRaises(KnitCorrupt, index.keys)
2484.1.13 by John Arbash Meinel
Add a test that KnitCorrupt is raised when parent strings are invalid.
1264
2484.1.18 by John Arbash Meinel
Test that we properly verify the size and position strings.
1265
    def test_invalid_position(self):
1266
        transport = MockTransport([
3350.6.4 by Robert Collins
First cut at pluralised VersionedFiles. Some rather massive API incompatabilities, primarily because of the difficulty of coherence among competing stores.
1267
            _KndxIndex.HEADER,
6985 by Jelmer Vernooij
Merge lp:~jelmer/brz/python3-weave-fmt.
1268
            b"a option 1v 1 :",
2484.1.18 by John Arbash Meinel
Test that we properly verify the size and position strings.
1269
            ])
3350.6.4 by Robert Collins
First cut at pluralised VersionedFiles. Some rather massive API incompatabilities, primarily because of the difficulty of coherence among competing stores.
1270
        index = self.get_knit_index(transport, 'filename', 'r')
6729.7.2 by Jelmer Vernooij
Finish move.
1271
        self.assertRaises(KnitCorrupt, index.keys)
2484.1.18 by John Arbash Meinel
Test that we properly verify the size and position strings.
1272
1273
    def test_invalid_size(self):
1274
        transport = MockTransport([
3350.6.4 by Robert Collins
First cut at pluralised VersionedFiles. Some rather massive API incompatabilities, primarily because of the difficulty of coherence among competing stores.
1275
            _KndxIndex.HEADER,
6985 by Jelmer Vernooij
Merge lp:~jelmer/brz/python3-weave-fmt.
1276
            b"a option 1 1v :",
2484.1.18 by John Arbash Meinel
Test that we properly verify the size and position strings.
1277
            ])
3350.6.4 by Robert Collins
First cut at pluralised VersionedFiles. Some rather massive API incompatabilities, primarily because of the difficulty of coherence among competing stores.
1278
        index = self.get_knit_index(transport, 'filename', 'r')
6729.7.2 by Jelmer Vernooij
Finish move.
1279
        self.assertRaises(KnitCorrupt, index.keys)
2484.1.18 by John Arbash Meinel
Test that we properly verify the size and position strings.
1280
4011.5.7 by Andrew Bennetts
Remove leading underscore from _scan_unvalidate_index, explicitly NotImplementedError it for _KndxIndex.
1281
    def test_scan_unvalidated_index_not_implemented(self):
1282
        transport = MockTransport()
1283
        index = self.get_knit_index(transport, 'filename', 'r')
1284
        self.assertRaises(
1285
            NotImplementedError, index.scan_unvalidated_index,
1286
            'dummy graph_index')
4011.5.11 by Robert Collins
Polish the KnitVersionedFiles.scan_unvalidated_index api.
1287
        self.assertRaises(
1288
            NotImplementedError, index.get_missing_compression_parents)
4011.5.7 by Andrew Bennetts
Remove leading underscore from _scan_unvalidate_index, explicitly NotImplementedError it for _KndxIndex.
1289
2484.1.24 by John Arbash Meinel
Add direct tests of how we handle incomplete/'broken' lines
1290
    def test_short_line(self):
1291
        transport = MockTransport([
3350.6.4 by Robert Collins
First cut at pluralised VersionedFiles. Some rather massive API incompatabilities, primarily because of the difficulty of coherence among competing stores.
1292
            _KndxIndex.HEADER,
6985 by Jelmer Vernooij
Merge lp:~jelmer/brz/python3-weave-fmt.
1293
            b"a option 0 10  :",
7143.15.2 by Jelmer Vernooij
Run autopep8.
1294
            b"b option 10 10 0",  # This line isn't terminated, ignored
2484.1.24 by John Arbash Meinel
Add direct tests of how we handle incomplete/'broken' lines
1295
            ])
1296
        index = self.get_knit_index(transport, "filename", "r")
6985 by Jelmer Vernooij
Merge lp:~jelmer/brz/python3-weave-fmt.
1297
        self.assertEqual({(b'a',)}, index.keys())
2484.1.24 by John Arbash Meinel
Add direct tests of how we handle incomplete/'broken' lines
1298
1299
    def test_skip_incomplete_record(self):
1300
        # A line with bogus data should just be skipped
1301
        transport = MockTransport([
3350.6.4 by Robert Collins
First cut at pluralised VersionedFiles. Some rather massive API incompatabilities, primarily because of the difficulty of coherence among competing stores.
1302
            _KndxIndex.HEADER,
6985 by Jelmer Vernooij
Merge lp:~jelmer/brz/python3-weave-fmt.
1303
            b"a option 0 10  :",
7143.15.2 by Jelmer Vernooij
Run autopep8.
1304
            b"b option 10 10 0",  # This line isn't terminated, ignored
1305
            b"c option 20 10 0 :",  # Properly terminated, and starts with '\n'
2484.1.24 by John Arbash Meinel
Add direct tests of how we handle incomplete/'broken' lines
1306
            ])
1307
        index = self.get_knit_index(transport, "filename", "r")
6985 by Jelmer Vernooij
Merge lp:~jelmer/brz/python3-weave-fmt.
1308
        self.assertEqual({(b'a',), (b'c',)}, index.keys())
2484.1.24 by John Arbash Meinel
Add direct tests of how we handle incomplete/'broken' lines
1309
1310
    def test_trailing_characters(self):
1311
        # A line with bogus data should just be skipped
1312
        transport = MockTransport([
3350.6.4 by Robert Collins
First cut at pluralised VersionedFiles. Some rather massive API incompatabilities, primarily because of the difficulty of coherence among competing stores.
1313
            _KndxIndex.HEADER,
6985 by Jelmer Vernooij
Merge lp:~jelmer/brz/python3-weave-fmt.
1314
            b"a option 0 10  :",
7143.15.2 by Jelmer Vernooij
Run autopep8.
1315
            b"b option 10 10 0 :a",  # This line has extra trailing characters
1316
            b"c option 20 10 0 :",  # Properly terminated, and starts with '\n'
2484.1.24 by John Arbash Meinel
Add direct tests of how we handle incomplete/'broken' lines
1317
            ])
1318
        index = self.get_knit_index(transport, "filename", "r")
6985 by Jelmer Vernooij
Merge lp:~jelmer/brz/python3-weave-fmt.
1319
        self.assertEqual({(b'a',), (b'c',)}, index.keys())
2484.1.24 by John Arbash Meinel
Add direct tests of how we handle incomplete/'broken' lines
1320
2158.3.1 by Dmitry Vasiliev
KnitIndex tests/fixes/optimizations
1321
2484.1.1 by John Arbash Meinel
Add an initial function to read knit indexes in pyrex.
1322
class LowLevelKnitIndexTests_c(LowLevelKnitIndexTests):
1323
4913.2.20 by John Arbash Meinel
Change all of the compiled_foo to compiled_foo_feature
1324
    _test_needs_features = [compiled_knit_feature]
2484.1.1 by John Arbash Meinel
Add an initial function to read knit indexes in pyrex.
1325
7027.1.2 by Martin
Fixup low level knit tests for Python 3
1326
    @property
1327
    def _load_data(self):
6670.4.3 by Jelmer Vernooij
Fix more imports.
1328
        from ..bzr._knit_load_data_pyx import _load_data_c
7027.1.2 by Martin
Fixup low level knit tests for Python 3
1329
        return _load_data_c
2484.1.1 by John Arbash Meinel
Add an initial function to read knit indexes in pyrex.
1330
1331
4454.3.28 by John Arbash Meinel
Continue breaking things to build it up cleanly.
1332
class Test_KnitAnnotator(TestCaseWithMemoryTransport):
1333
1334
    def make_annotator(self):
1335
        factory = knit.make_pack_factory(True, True, 1)
1336
        vf = factory(self.get_transport())
1337
        return knit._KnitAnnotator(vf)
1338
1339
    def test__expand_fulltext(self):
1340
        ann = self.make_annotator()
6963.2.4 by Jelmer Vernooij
Add bees.
1341
        rev_key = (b'rev-id',)
4454.3.36 by John Arbash Meinel
Only cache the content objects that we will reuse.
1342
        ann._num_compression_children[rev_key] = 1
6963.2.4 by Jelmer Vernooij
Add bees.
1343
        res = ann._expand_record(rev_key, ((b'parent-id',),), None,
7143.15.2 by Jelmer Vernooij
Run autopep8.
1344
                                 [b'line1\n', b'line2\n'], ('fulltext', True))
4454.3.28 by John Arbash Meinel
Continue breaking things to build it up cleanly.
1345
        # The content object and text lines should be cached appropriately
6963.2.4 by Jelmer Vernooij
Add bees.
1346
        self.assertEqual([b'line1\n', b'line2'], res)
4454.3.28 by John Arbash Meinel
Continue breaking things to build it up cleanly.
1347
        content_obj = ann._content_objects[rev_key]
6963.2.4 by Jelmer Vernooij
Add bees.
1348
        self.assertEqual([b'line1\n', b'line2\n'], content_obj._lines)
4454.3.28 by John Arbash Meinel
Continue breaking things to build it up cleanly.
1349
        self.assertEqual(res, content_obj.text())
1350
        self.assertEqual(res, ann._text_cache[rev_key])
1351
4454.3.30 by John Arbash Meinel
add a bit more work to be able to process 'pending_annotations'.
1352
    def test__expand_delta_comp_parent_not_available(self):
4454.3.28 by John Arbash Meinel
Continue breaking things to build it up cleanly.
1353
        # Parent isn't available yet, so we return nothing, but queue up this
1354
        # node for later processing
1355
        ann = self.make_annotator()
6985 by Jelmer Vernooij
Merge lp:~jelmer/brz/python3-weave-fmt.
1356
        rev_key = (b'rev-id',)
1357
        parent_key = (b'parent-id',)
1358
        record = [b'0,1,1\n', b'new-line\n']
4454.3.28 by John Arbash Meinel
Continue breaking things to build it up cleanly.
1359
        details = ('line-delta', False)
1360
        res = ann._expand_record(rev_key, (parent_key,), parent_key,
1361
                                 record, details)
1362
        self.assertEqual(None, res)
1363
        self.assertTrue(parent_key in ann._pending_deltas)
1364
        pending = ann._pending_deltas[parent_key]
1365
        self.assertEqual(1, len(pending))
1366
        self.assertEqual((rev_key, (parent_key,), record, details), pending[0])
1367
4454.3.33 by John Arbash Meinel
Change the _expand_record code to pop out old content objects.
1368
    def test__expand_record_tracks_num_children(self):
1369
        ann = self.make_annotator()
6963.2.3 by Jelmer Vernooij
Fix some more tests.
1370
        rev_key = (b'rev-id',)
1371
        rev2_key = (b'rev2-id',)
1372
        parent_key = (b'parent-id',)
1373
        record = [b'0,1,1\n', b'new-line\n']
6985 by Jelmer Vernooij
Merge lp:~jelmer/brz/python3-weave-fmt.
1374
        details = ('line-delta', False)
4454.3.33 by John Arbash Meinel
Change the _expand_record code to pop out old content objects.
1375
        ann._num_compression_children[parent_key] = 2
6963.2.3 by Jelmer Vernooij
Fix some more tests.
1376
        ann._expand_record(parent_key, (), None, [b'line1\n', b'line2\n'],
7078.6.1 by Jelmer Vernooij
Fix corrupt knit handling on Python 3.
1377
                           ('fulltext', False))
4454.3.33 by John Arbash Meinel
Change the _expand_record code to pop out old content objects.
1378
        res = ann._expand_record(rev_key, (parent_key,), parent_key,
1379
                                 record, details)
1380
        self.assertEqual({parent_key: 1}, ann._num_compression_children)
1381
        # Expanding the second child should remove the content object, and the
1382
        # num_compression_children entry
1383
        res = ann._expand_record(rev2_key, (parent_key,), parent_key,
1384
                                 record, details)
1385
        self.assertFalse(parent_key in ann._content_objects)
1386
        self.assertEqual({}, ann._num_compression_children)
4454.3.36 by John Arbash Meinel
Only cache the content objects that we will reuse.
1387
        # We should not cache the content_objects for rev2 and rev, because
1388
        # they do not have compression children of their own.
1389
        self.assertEqual({}, ann._content_objects)
4454.3.33 by John Arbash Meinel
Change the _expand_record code to pop out old content objects.
1390
4454.3.37 by John Arbash Meinel
Add tests tha left-matching-blocks gets populated.
1391
    def test__expand_delta_records_blocks(self):
1392
        ann = self.make_annotator()
6963.2.3 by Jelmer Vernooij
Fix some more tests.
1393
        rev_key = (b'rev-id',)
1394
        parent_key = (b'parent-id',)
1395
        record = [b'0,1,1\n', b'new-line\n']
6985 by Jelmer Vernooij
Merge lp:~jelmer/brz/python3-weave-fmt.
1396
        details = ('line-delta', True)
4454.3.37 by John Arbash Meinel
Add tests tha left-matching-blocks gets populated.
1397
        ann._num_compression_children[parent_key] = 2
1398
        ann._expand_record(parent_key, (), None,
6963.2.3 by Jelmer Vernooij
Fix some more tests.
1399
                           [b'line1\n', b'line2\n', b'line3\n'],
7078.6.1 by Jelmer Vernooij
Fix corrupt knit handling on Python 3.
1400
                           ('fulltext', False))
4454.3.37 by John Arbash Meinel
Add tests tha left-matching-blocks gets populated.
1401
        ann._expand_record(rev_key, (parent_key,), parent_key, record, details)
4454.3.38 by John Arbash Meinel
Start using left-matching-blocks during the actual annotation.
1402
        self.assertEqual({(rev_key, parent_key): [(1, 1, 1), (3, 3, 0)]},
1403
                         ann._matching_blocks)
6963.2.3 by Jelmer Vernooij
Fix some more tests.
1404
        rev2_key = (b'rev2-id',)
6963.2.4 by Jelmer Vernooij
Add bees.
1405
        record = [b'0,1,1\n', b'new-line\n']
6985 by Jelmer Vernooij
Merge lp:~jelmer/brz/python3-weave-fmt.
1406
        details = ('line-delta', False)
7143.15.2 by Jelmer Vernooij
Run autopep8.
1407
        ann._expand_record(rev2_key, (parent_key,),
1408
                           parent_key, record, details)
4454.3.37 by John Arbash Meinel
Add tests tha left-matching-blocks gets populated.
1409
        self.assertEqual([(1, 1, 2), (3, 3, 0)],
4454.3.38 by John Arbash Meinel
Start using left-matching-blocks during the actual annotation.
1410
                         ann._matching_blocks[(rev2_key, parent_key)])
1411
1412
    def test__get_parent_ann_uses_matching_blocks(self):
1413
        ann = self.make_annotator()
6963.2.3 by Jelmer Vernooij
Fix some more tests.
1414
        rev_key = (b'rev-id',)
1415
        parent_key = (b'parent-id',)
7143.15.2 by Jelmer Vernooij
Run autopep8.
1416
        parent_ann = [(parent_key,)] * 3
4454.3.38 by John Arbash Meinel
Start using left-matching-blocks during the actual annotation.
1417
        block_key = (rev_key, parent_key)
1418
        ann._annotations_cache[parent_key] = parent_ann
1419
        ann._matching_blocks[block_key] = [(0, 1, 1), (3, 3, 0)]
1420
        # We should not try to access any parent_lines content, because we know
1421
        # we already have the matching blocks
1422
        par_ann, blocks = ann._get_parent_annotations_and_matches(rev_key,
7143.15.2 by Jelmer Vernooij
Run autopep8.
1423
                                                                  [b'1\n', b'2\n', b'3\n'], parent_key)
4454.3.38 by John Arbash Meinel
Start using left-matching-blocks during the actual annotation.
1424
        self.assertEqual(parent_ann, par_ann)
1425
        self.assertEqual([(0, 1, 1), (3, 3, 0)], blocks)
1426
        self.assertEqual({}, ann._matching_blocks)
4454.3.37 by John Arbash Meinel
Add tests tha left-matching-blocks gets populated.
1427
4454.3.31 by John Arbash Meinel
Change the processing lines to now handle fallbacks properly.
1428
    def test__process_pending(self):
4454.3.30 by John Arbash Meinel
add a bit more work to be able to process 'pending_annotations'.
1429
        ann = self.make_annotator()
6963.2.3 by Jelmer Vernooij
Fix some more tests.
1430
        rev_key = (b'rev-id',)
1431
        p1_key = (b'p1-id',)
1432
        p2_key = (b'p2-id',)
1433
        record = [b'0,1,1\n', b'new-line\n']
6985 by Jelmer Vernooij
Merge lp:~jelmer/brz/python3-weave-fmt.
1434
        details = ('line-delta', False)
6963.2.3 by Jelmer Vernooij
Fix some more tests.
1435
        p1_record = [b'line1\n', b'line2\n']
4454.3.33 by John Arbash Meinel
Change the _expand_record code to pop out old content objects.
1436
        ann._num_compression_children[p1_key] = 1
6809.1.1 by Martin
Apply 2to3 ws_comma fixer
1437
        res = ann._expand_record(rev_key, (p1_key, p2_key), p1_key,
4454.3.30 by John Arbash Meinel
add a bit more work to be able to process 'pending_annotations'.
1438
                                 record, details)
1439
        self.assertEqual(None, res)
1440
        # self.assertTrue(p1_key in ann._pending_deltas)
1441
        self.assertEqual({}, ann._pending_annotation)
1442
        # Now insert p1, and we should be able to expand the delta
1443
        res = ann._expand_record(p1_key, (), None, p1_record,
7078.6.1 by Jelmer Vernooij
Fix corrupt knit handling on Python 3.
1444
                                 ('fulltext', False))
4454.3.30 by John Arbash Meinel
add a bit more work to be able to process 'pending_annotations'.
1445
        self.assertEqual(p1_record, res)
7143.15.2 by Jelmer Vernooij
Run autopep8.
1446
        ann._annotations_cache[p1_key] = [(p1_key,)] * 2
4454.3.30 by John Arbash Meinel
add a bit more work to be able to process 'pending_annotations'.
1447
        res = ann._process_pending(p1_key)
4454.3.31 by John Arbash Meinel
Change the processing lines to now handle fallbacks properly.
1448
        self.assertEqual([], res)
4454.3.30 by John Arbash Meinel
add a bit more work to be able to process 'pending_annotations'.
1449
        self.assertFalse(p1_key in ann._pending_deltas)
1450
        self.assertTrue(p2_key in ann._pending_annotation)
1451
        self.assertEqual({p2_key: [(rev_key, (p1_key, p2_key))]},
1452
                         ann._pending_annotation)
1453
        # Now fill in parent 2, and pending annotation should be satisfied
7078.6.1 by Jelmer Vernooij
Fix corrupt knit handling on Python 3.
1454
        res = ann._expand_record(p2_key, (), None, [], ('fulltext', False))
4454.3.31 by John Arbash Meinel
Change the processing lines to now handle fallbacks properly.
1455
        ann._annotations_cache[p2_key] = []
1456
        res = ann._process_pending(p2_key)
1457
        self.assertEqual([rev_key], res)
1458
        self.assertEqual({}, ann._pending_annotation)
1459
        self.assertEqual({}, ann._pending_deltas)
4454.3.30 by John Arbash Meinel
add a bit more work to be able to process 'pending_annotations'.
1460
4454.3.28 by John Arbash Meinel
Continue breaking things to build it up cleanly.
1461
    def test_record_delta_removes_basis(self):
1462
        ann = self.make_annotator()
6963.2.3 by Jelmer Vernooij
Fix some more tests.
1463
        ann._expand_record((b'parent-id',), (), None,
7078.6.1 by Jelmer Vernooij
Fix corrupt knit handling on Python 3.
1464
                           [b'line1\n', b'line2\n'], ('fulltext', False))
6963.2.3 by Jelmer Vernooij
Fix some more tests.
1465
        ann._num_compression_children[b'parent-id'] = 2
4454.3.28 by John Arbash Meinel
Continue breaking things to build it up cleanly.
1466
4454.3.64 by John Arbash Meinel
Ensure that _KnitAnnotator also supports add_special_text.
1467
    def test_annotate_special_text(self):
1468
        ann = self.make_annotator()
1469
        vf = ann._vf
6973.14.2 by Jelmer Vernooij
Fix some knit tests.
1470
        rev1_key = (b'rev-1',)
1471
        rev2_key = (b'rev-2',)
1472
        rev3_key = (b'rev-3',)
1473
        spec_key = (b'special:',)
1474
        vf.add_lines(rev1_key, [], [b'initial content\n'])
1475
        vf.add_lines(rev2_key, [rev1_key], [b'initial content\n',
1476
                                            b'common content\n',
1477
                                            b'content in 2\n'])
1478
        vf.add_lines(rev3_key, [rev1_key], [b'initial content\n',
1479
                                            b'common content\n',
1480
                                            b'content in 3\n'])
1481
        spec_text = (b'initial content\n'
1482
                     b'common content\n'
1483
                     b'content in 2\n'
1484
                     b'content in 3\n')
4454.3.64 by John Arbash Meinel
Ensure that _KnitAnnotator also supports add_special_text.
1485
        ann.add_special_text(spec_key, [rev2_key, rev3_key], spec_text)
1486
        anns, lines = ann.annotate(spec_key)
1487
        self.assertEqual([(rev1_key,),
1488
                          (rev2_key, rev3_key),
1489
                          (rev2_key,),
1490
                          (rev3_key,),
7143.15.2 by Jelmer Vernooij
Run autopep8.
1491
                          ], anns)
6973.14.2 by Jelmer Vernooij
Fix some knit tests.
1492
        self.assertEqualDiff(spec_text, b''.join(lines))
4454.3.64 by John Arbash Meinel
Ensure that _KnitAnnotator also supports add_special_text.
1493
4454.3.28 by John Arbash Meinel
Continue breaking things to build it up cleanly.
1494
1684.3.3 by Robert Collins
Add a special cased weaves to knit converter.
1495
class KnitTests(TestCaseWithTransport):
1496
    """Class containing knit test helper routines."""
1563.2.16 by Robert Collins
Change WeaveStore into VersionedFileStore and make its versoined file class parameterisable.
1497
3350.6.4 by Robert Collins
First cut at pluralised VersionedFiles. Some rather massive API incompatabilities, primarily because of the difficulty of coherence among competing stores.
1498
    def make_test_knit(self, annotate=False, name='test'):
1499
        mapper = ConstantMapper(name)
1500
        return make_file_factory(annotate, mapper)(self.get_transport())
1863.1.1 by John Arbash Meinel
Allow Versioned files to do caching if explicitly asked, and implement for Knit
1501
1502
3787.1.1 by Robert Collins
Embed the failed text in sha1 knit errors.
1503
class TestBadShaError(KnitTests):
1504
    """Tests for handling of sha errors."""
1505
4005.3.6 by Robert Collins
Support delta_closure=True with NetworkRecordStream to transmit deltas over the wire when full text extraction is required on the far end.
1506
    def test_sha_exception_has_text(self):
3787.1.1 by Robert Collins
Embed the failed text in sha1 knit errors.
1507
        # having the failed text included in the error allows for recovery.
1508
        source = self.make_test_knit()
1509
        target = self.make_test_knit(name="target")
1510
        if not source._max_delta_chain:
1511
            raise TestNotApplicable(
1512
                "cannot get delta-caused sha failures without deltas.")
1513
        # create a basis
6973.14.2 by Jelmer Vernooij
Fix some knit tests.
1514
        basis = (b'basis',)
1515
        broken = (b'broken',)
1516
        source.add_lines(basis, (), [b'foo\n'])
1517
        source.add_lines(broken, (basis,), [b'foo\n', b'bar\n'])
3787.1.1 by Robert Collins
Embed the failed text in sha1 knit errors.
1518
        # Seed target with a bad basis text
6973.14.2 by Jelmer Vernooij
Fix some knit tests.
1519
        target.add_lines(basis, (), [b'gam\n'])
3787.1.1 by Robert Collins
Embed the failed text in sha1 knit errors.
1520
        target.insert_record_stream(
1521
            source.get_record_stream([broken], 'unordered', False))
6729.7.2 by Jelmer Vernooij
Finish move.
1522
        err = self.assertRaises(KnitCorrupt,
7143.15.2 by Jelmer Vernooij
Run autopep8.
1523
                                next(target.get_record_stream([broken], 'unordered', True
1524
                                                              )).get_bytes_as, 'chunked')
6973.14.2 by Jelmer Vernooij
Fix some knit tests.
1525
        self.assertEqual([b'gam\n', b'bar\n'], err.content)
3787.1.2 by Robert Collins
Ensure SHA1KnitCorrupt formats ok.
1526
        # Test for formatting with live data
1527
        self.assertStartsWith(str(err), "Knit ")
3787.1.1 by Robert Collins
Embed the failed text in sha1 knit errors.
1528
1529
2102.2.1 by John Arbash Meinel
Fix bug #64789 _KnitIndex.add_versions() should dict compress new revisions
1530
class TestKnitIndex(KnitTests):
1531
1532
    def test_add_versions_dictionary_compresses(self):
1533
        """Adding versions to the index should update the lookup dict"""
1534
        knit = self.make_test_knit()
1535
        idx = knit._index
6973.14.2 by Jelmer Vernooij
Fix some knit tests.
1536
        idx.add_records([((b'a-1',), [b'fulltext'], ((b'a-1',), 0, 0), [])])
2102.2.1 by John Arbash Meinel
Fix bug #64789 _KnitIndex.add_versions() should dict compress new revisions
1537
        self.check_file_contents('test.kndx',
7143.15.2 by Jelmer Vernooij
Run autopep8.
1538
                                 b'# bzr knit index 8\n'
1539
                                 b'\n'
1540
                                 b'a-1 fulltext 0 0  :'
1541
                                 )
3350.6.4 by Robert Collins
First cut at pluralised VersionedFiles. Some rather massive API incompatabilities, primarily because of the difficulty of coherence among competing stores.
1542
        idx.add_records([
6973.14.2 by Jelmer Vernooij
Fix some knit tests.
1543
            ((b'a-2',), [b'fulltext'], ((b'a-2',), 0, 0), [(b'a-1',)]),
1544
            ((b'a-3',), [b'fulltext'], ((b'a-3',), 0, 0), [(b'a-2',)]),
3350.6.4 by Robert Collins
First cut at pluralised VersionedFiles. Some rather massive API incompatabilities, primarily because of the difficulty of coherence among competing stores.
1545
            ])
2102.2.1 by John Arbash Meinel
Fix bug #64789 _KnitIndex.add_versions() should dict compress new revisions
1546
        self.check_file_contents('test.kndx',
7143.15.2 by Jelmer Vernooij
Run autopep8.
1547
                                 b'# bzr knit index 8\n'
1548
                                 b'\n'
1549
                                 b'a-1 fulltext 0 0  :\n'
1550
                                 b'a-2 fulltext 0 0 0 :\n'
1551
                                 b'a-3 fulltext 0 0 1 :'
1552
                                 )
6973.14.2 by Jelmer Vernooij
Fix some knit tests.
1553
        self.assertEqual({(b'a-3',), (b'a-1',), (b'a-2',)}, idx.keys())
3350.6.4 by Robert Collins
First cut at pluralised VersionedFiles. Some rather massive API incompatabilities, primarily because of the difficulty of coherence among competing stores.
1554
        self.assertEqual({
6973.14.2 by Jelmer Vernooij
Fix some knit tests.
1555
            (b'a-1',): (((b'a-1',), 0, 0), None, (), ('fulltext', False)),
1556
            (b'a-2',): (((b'a-2',), 0, 0), None, ((b'a-1',),), ('fulltext', False)),
1557
            (b'a-3',): (((b'a-3',), 0, 0), None, ((b'a-2',),), ('fulltext', False)),
3350.6.4 by Robert Collins
First cut at pluralised VersionedFiles. Some rather massive API incompatabilities, primarily because of the difficulty of coherence among competing stores.
1558
            }, idx.get_build_details(idx.keys()))
6973.14.2 by Jelmer Vernooij
Fix some knit tests.
1559
        self.assertEqual({(b'a-1',): (),
7143.15.2 by Jelmer Vernooij
Run autopep8.
1560
                          (b'a-2',): ((b'a-1',),),
1561
                          (b'a-3',): ((b'a-2',),), },
1562
                         idx.get_parent_map(idx.keys()))
2102.2.1 by John Arbash Meinel
Fix bug #64789 _KnitIndex.add_versions() should dict compress new revisions
1563
1564
    def test_add_versions_fails_clean(self):
1565
        """If add_versions fails in the middle, it restores a pristine state.
1566
1567
        Any modifications that are made to the index are reset if all versions
1568
        cannot be added.
1569
        """
1570
        # This cheats a little bit by passing in a generator which will
1571
        # raise an exception before the processing finishes
1572
        # Other possibilities would be to have an version with the wrong number
1573
        # of entries, or to make the backing transport unable to write any
1574
        # files.
1575
1576
        knit = self.make_test_knit()
1577
        idx = knit._index
6973.14.2 by Jelmer Vernooij
Fix some knit tests.
1578
        idx.add_records([((b'a-1',), [b'fulltext'], ((b'a-1',), 0, 0), [])])
2102.2.1 by John Arbash Meinel
Fix bug #64789 _KnitIndex.add_versions() should dict compress new revisions
1579
1580
        class StopEarly(Exception):
1581
            pass
1582
1583
        def generate_failure():
1584
            """Add some entries and then raise an exception"""
6973.14.2 by Jelmer Vernooij
Fix some knit tests.
1585
            yield ((b'a-2',), [b'fulltext'], (None, 0, 0), (b'a-1',))
1586
            yield ((b'a-3',), [b'fulltext'], (None, 0, 0), (b'a-2',))
2102.2.1 by John Arbash Meinel
Fix bug #64789 _KnitIndex.add_versions() should dict compress new revisions
1587
            raise StopEarly()
1588
1589
        # Assert the pre-condition
3350.6.4 by Robert Collins
First cut at pluralised VersionedFiles. Some rather massive API incompatabilities, primarily because of the difficulty of coherence among competing stores.
1590
        def assertA1Only():
6973.14.2 by Jelmer Vernooij
Fix some knit tests.
1591
            self.assertEqual({(b'a-1',)}, set(idx.keys()))
3350.6.4 by Robert Collins
First cut at pluralised VersionedFiles. Some rather massive API incompatabilities, primarily because of the difficulty of coherence among competing stores.
1592
            self.assertEqual(
6973.14.2 by Jelmer Vernooij
Fix some knit tests.
1593
                {(b'a-1',): (((b'a-1',), 0, 0), None, (), ('fulltext', False))},
1594
                idx.get_build_details([(b'a-1',)]))
7143.15.2 by Jelmer Vernooij
Run autopep8.
1595
            self.assertEqual({(b'a-1',): ()}, idx.get_parent_map(idx.keys()))
3350.6.4 by Robert Collins
First cut at pluralised VersionedFiles. Some rather massive API incompatabilities, primarily because of the difficulty of coherence among competing stores.
1596
1597
        assertA1Only()
1598
        self.assertRaises(StopEarly, idx.add_records, generate_failure())
2102.2.1 by John Arbash Meinel
Fix bug #64789 _KnitIndex.add_versions() should dict compress new revisions
1599
        # And it shouldn't be modified
3350.6.4 by Robert Collins
First cut at pluralised VersionedFiles. Some rather massive API incompatabilities, primarily because of the difficulty of coherence among competing stores.
1600
        assertA1Only()
2171.1.1 by John Arbash Meinel
Knit index files should ignore empty indexes rather than consider them corrupt.
1601
1602
    def test_knit_index_ignores_empty_files(self):
1603
        # There was a race condition in older bzr, where a ^C at the right time
1604
        # could leave an empty .kndx file, which bzr would later claim was a
1605
        # corrupted file since the header was not present. In reality, the file
1606
        # just wasn't created, so it should be ignored.
6083.1.1 by Jelmer Vernooij
Use get_transport_from_{url,path} in more places.
1607
        t = transport.get_transport_from_path('.')
6973.14.2 by Jelmer Vernooij
Fix some knit tests.
1608
        t.put_bytes('test.kndx', b'')
2171.1.1 by John Arbash Meinel
Knit index files should ignore empty indexes rather than consider them corrupt.
1609
1610
        knit = self.make_test_knit()
1611
1612
    def test_knit_index_checks_header(self):
6083.1.1 by Jelmer Vernooij
Use get_transport_from_{url,path} in more places.
1613
        t = transport.get_transport_from_path('.')
6985 by Jelmer Vernooij
Merge lp:~jelmer/brz/python3-weave-fmt.
1614
        t.put_bytes('test.kndx', b'# not really a knit header\n\n')
3350.6.4 by Robert Collins
First cut at pluralised VersionedFiles. Some rather massive API incompatabilities, primarily because of the difficulty of coherence among competing stores.
1615
        k = self.make_test_knit()
1616
        self.assertRaises(KnitHeaderError, k.keys)
2592.3.2 by Robert Collins
Implement a get_graph for a new KnitGraphIndex that will implement a KnitIndex on top of the GraphIndex API.
1617
1618
1619
class TestGraphIndexKnit(KnitTests):
1620
    """Tests for knits using a GraphIndex rather than a KnitIndex."""
1621
1622
    def make_g_index(self, name, ref_lists=0, nodes=[]):
1623
        builder = GraphIndexBuilder(ref_lists)
1624
        for node, references, value in nodes:
1625
            builder.add_node(node, references, value)
1626
        stream = builder.finish()
1627
        trans = self.get_transport()
2890.2.1 by Robert Collins
* ``bzrlib.index.GraphIndex`` now requires a size parameter to the
1628
        size = trans.put_file(name, stream)
1629
        return GraphIndex(trans, name, size)
2592.3.2 by Robert Collins
Implement a get_graph for a new KnitGraphIndex that will implement a KnitIndex on top of the GraphIndex API.
1630
2592.3.19 by Robert Collins
Change KnitGraphIndex from returning data to performing a callback on insertions.
1631
    def two_graph_index(self, deltas=False, catch_adds=False):
2592.3.13 by Robert Collins
Implement KnitGraphIndex.get_method.
1632
        """Build a two-graph index.
1633
1634
        :param deltas: If true, use underlying indices with two node-ref
1635
            lists and 'parent' set to a delta-compressed against tail.
1636
        """
2592.3.2 by Robert Collins
Implement a get_graph for a new KnitGraphIndex that will implement a KnitIndex on top of the GraphIndex API.
1637
        # build a complex graph across several indices.
2592.3.13 by Robert Collins
Implement KnitGraphIndex.get_method.
1638
        if deltas:
2624.2.5 by Robert Collins
Change bzrlib.index.Index keys to be 1-tuples, not strings.
1639
            # delta compression inn the index
2592.3.13 by Robert Collins
Implement KnitGraphIndex.get_method.
1640
            index1 = self.make_g_index('1', 2, [
6973.14.2 by Jelmer Vernooij
Fix some knit tests.
1641
                ((b'tip', ), b'N0 100', ([(b'parent', )], [], )),
1642
                ((b'tail', ), b'', ([], []))])
2592.3.13 by Robert Collins
Implement KnitGraphIndex.get_method.
1643
            index2 = self.make_g_index('2', 2, [
7143.15.2 by Jelmer Vernooij
Run autopep8.
1644
                ((b'parent', ), b' 100 78',
1645
                 ([(b'tail', ), (b'ghost', )], [(b'tail', )])),
6973.14.2 by Jelmer Vernooij
Fix some knit tests.
1646
                ((b'separate', ), b'', ([], []))])
2592.3.13 by Robert Collins
Implement KnitGraphIndex.get_method.
1647
        else:
2624.2.5 by Robert Collins
Change bzrlib.index.Index keys to be 1-tuples, not strings.
1648
            # just blob location and graph in the index.
2592.3.13 by Robert Collins
Implement KnitGraphIndex.get_method.
1649
            index1 = self.make_g_index('1', 1, [
6973.14.2 by Jelmer Vernooij
Fix some knit tests.
1650
                ((b'tip', ), b'N0 100', ([(b'parent', )], )),
1651
                ((b'tail', ), b'', ([], ))])
2592.3.13 by Robert Collins
Implement KnitGraphIndex.get_method.
1652
            index2 = self.make_g_index('2', 1, [
6973.14.2 by Jelmer Vernooij
Fix some knit tests.
1653
                ((b'parent', ), b' 100 78', ([(b'tail', ), (b'ghost', )], )),
1654
                ((b'separate', ), b'', ([], ))])
2592.3.2 by Robert Collins
Implement a get_graph for a new KnitGraphIndex that will implement a KnitIndex on top of the GraphIndex API.
1655
        combined_index = CombinedGraphIndex([index1, index2])
2592.3.19 by Robert Collins
Change KnitGraphIndex from returning data to performing a callback on insertions.
1656
        if catch_adds:
1657
            self.combined_index = combined_index
1658
            self.caught_entries = []
1659
            add_callback = self.catch_add
1660
        else:
1661
            add_callback = None
7143.15.2 by Jelmer Vernooij
Run autopep8.
1662
        return _KnitGraphIndex(combined_index, lambda: True, deltas=deltas,
1663
                               add_callback=add_callback)
2592.3.4 by Robert Collins
Implement get_ancestry/get_ancestry_with_ghosts for KnitGraphIndex.
1664
3350.6.4 by Robert Collins
First cut at pluralised VersionedFiles. Some rather massive API incompatabilities, primarily because of the difficulty of coherence among competing stores.
1665
    def test_keys(self):
1666
        index = self.two_graph_index()
6985 by Jelmer Vernooij
Merge lp:~jelmer/brz/python3-weave-fmt.
1667
        self.assertEqual({(b'tail',), (b'tip',), (b'parent',), (b'separate',)},
7143.15.2 by Jelmer Vernooij
Run autopep8.
1668
                         set(index.keys()))
2592.3.9 by Robert Collins
Implement KnitGraphIndex.has_version.
1669
2592.3.10 by Robert Collins
Implement KnitGraphIndex.get_position.
1670
    def test_get_position(self):
1671
        index = self.two_graph_index()
7143.15.2 by Jelmer Vernooij
Run autopep8.
1672
        self.assertEqual(
1673
            (index._graph_index._indices[0], 0, 100), index.get_position((b'tip',)))
1674
        self.assertEqual(
1675
            (index._graph_index._indices[1], 100, 78), index.get_position((b'parent',)))
2592.3.10 by Robert Collins
Implement KnitGraphIndex.get_position.
1676
2592.3.13 by Robert Collins
Implement KnitGraphIndex.get_method.
1677
    def test_get_method_deltas(self):
1678
        index = self.two_graph_index(deltas=True)
6985 by Jelmer Vernooij
Merge lp:~jelmer/brz/python3-weave-fmt.
1679
        self.assertEqual('fulltext', index.get_method((b'tip',)))
1680
        self.assertEqual('line-delta', index.get_method((b'parent',)))
2592.3.11 by Robert Collins
Implement KnitGraphIndex.get_method.
1681
2592.3.13 by Robert Collins
Implement KnitGraphIndex.get_method.
1682
    def test_get_method_no_deltas(self):
1683
        # check that the parent-history lookup is ignored with deltas=False.
1684
        index = self.two_graph_index(deltas=False)
6985 by Jelmer Vernooij
Merge lp:~jelmer/brz/python3-weave-fmt.
1685
        self.assertEqual('fulltext', index.get_method((b'tip',)))
1686
        self.assertEqual('fulltext', index.get_method((b'parent',)))
2592.3.13 by Robert Collins
Implement KnitGraphIndex.get_method.
1687
2592.3.14 by Robert Collins
Implement KnitGraphIndex.get_options.
1688
    def test_get_options_deltas(self):
1689
        index = self.two_graph_index(deltas=True)
7143.15.2 by Jelmer Vernooij
Run autopep8.
1690
        self.assertEqual([b'fulltext', b'no-eol'],
1691
                         index.get_options((b'tip',)))
6973.14.2 by Jelmer Vernooij
Fix some knit tests.
1692
        self.assertEqual([b'line-delta'], index.get_options((b'parent',)))
2592.3.14 by Robert Collins
Implement KnitGraphIndex.get_options.
1693
1694
    def test_get_options_no_deltas(self):
1695
        # check that the parent-history lookup is ignored with deltas=False.
1696
        index = self.two_graph_index(deltas=False)
7143.15.2 by Jelmer Vernooij
Run autopep8.
1697
        self.assertEqual([b'fulltext', b'no-eol'],
1698
                         index.get_options((b'tip',)))
6973.14.2 by Jelmer Vernooij
Fix some knit tests.
1699
        self.assertEqual([b'fulltext'], index.get_options((b'parent',)))
3350.6.4 by Robert Collins
First cut at pluralised VersionedFiles. Some rather massive API incompatabilities, primarily because of the difficulty of coherence among competing stores.
1700
1701
    def test_get_parent_map(self):
1702
        index = self.two_graph_index()
7143.15.2 by Jelmer Vernooij
Run autopep8.
1703
        self.assertEqual({(b'parent',): ((b'tail',), (b'ghost',))},
1704
                         index.get_parent_map([(b'parent',), (b'ghost',)]))
2592.3.14 by Robert Collins
Implement KnitGraphIndex.get_options.
1705
2592.3.19 by Robert Collins
Change KnitGraphIndex from returning data to performing a callback on insertions.
1706
    def catch_add(self, entries):
1707
        self.caught_entries.append(entries)
1708
1709
    def test_add_no_callback_errors(self):
1710
        index = self.two_graph_index()
3350.6.4 by Robert Collins
First cut at pluralised VersionedFiles. Some rather massive API incompatabilities, primarily because of the difficulty of coherence among competing stores.
1711
        self.assertRaises(errors.ReadOnlyError, index.add_records,
7143.15.2 by Jelmer Vernooij
Run autopep8.
1712
                          [((b'new',), b'fulltext,no-eol', (None, 50, 60), [b'separate'])])
2592.3.19 by Robert Collins
Change KnitGraphIndex from returning data to performing a callback on insertions.
1713
2592.3.17 by Robert Collins
Add add_version(s) to KnitGraphIndex, completing the required api for KnitVersionedFile.
1714
    def test_add_version_smoke(self):
2592.3.19 by Robert Collins
Change KnitGraphIndex from returning data to performing a callback on insertions.
1715
        index = self.two_graph_index(catch_adds=True)
6973.14.2 by Jelmer Vernooij
Fix some knit tests.
1716
        index.add_records([((b'new',), b'fulltext,no-eol', (None, 50, 60),
7143.15.2 by Jelmer Vernooij
Run autopep8.
1717
                            [(b'separate',)])])
6973.14.2 by Jelmer Vernooij
Fix some knit tests.
1718
        self.assertEqual([[((b'new', ), b'N50 60', (((b'separate',),),))]],
7143.15.2 by Jelmer Vernooij
Run autopep8.
1719
                         self.caught_entries)
2592.3.17 by Robert Collins
Add add_version(s) to KnitGraphIndex, completing the required api for KnitVersionedFile.
1720
1721
    def test_add_version_delta_not_delta_index(self):
2592.3.19 by Robert Collins
Change KnitGraphIndex from returning data to performing a callback on insertions.
1722
        index = self.two_graph_index(catch_adds=True)
6729.7.2 by Jelmer Vernooij
Finish move.
1723
        self.assertRaises(KnitCorrupt, index.add_records,
7143.15.2 by Jelmer Vernooij
Run autopep8.
1724
                          [((b'new',), b'no-eol,line-delta', (None, 0, 100), [(b'parent',)])])
2592.3.19 by Robert Collins
Change KnitGraphIndex from returning data to performing a callback on insertions.
1725
        self.assertEqual([], self.caught_entries)
2592.3.17 by Robert Collins
Add add_version(s) to KnitGraphIndex, completing the required api for KnitVersionedFile.
1726
1727
    def test_add_version_same_dup(self):
2592.3.19 by Robert Collins
Change KnitGraphIndex from returning data to performing a callback on insertions.
1728
        index = self.two_graph_index(catch_adds=True)
2592.3.17 by Robert Collins
Add add_version(s) to KnitGraphIndex, completing the required api for KnitVersionedFile.
1729
        # options can be spelt two different ways
7143.15.2 by Jelmer Vernooij
Run autopep8.
1730
        index.add_records(
1731
            [((b'tip',), b'fulltext,no-eol', (None, 0, 100), [(b'parent',)])])
1732
        index.add_records(
1733
            [((b'tip',), b'no-eol,fulltext', (None, 0, 100), [(b'parent',)])])
3350.6.4 by Robert Collins
First cut at pluralised VersionedFiles. Some rather massive API incompatabilities, primarily because of the difficulty of coherence among competing stores.
1734
        # position/length are ignored (because each pack could have fulltext or
1735
        # delta, and be at a different position.
6973.14.2 by Jelmer Vernooij
Fix some knit tests.
1736
        index.add_records([((b'tip',), b'fulltext,no-eol', (None, 50, 100),
7143.15.2 by Jelmer Vernooij
Run autopep8.
1737
                            [(b'parent',)])])
6973.14.2 by Jelmer Vernooij
Fix some knit tests.
1738
        index.add_records([((b'tip',), b'fulltext,no-eol', (None, 0, 1000),
7143.15.2 by Jelmer Vernooij
Run autopep8.
1739
                            [(b'parent',)])])
3350.6.4 by Robert Collins
First cut at pluralised VersionedFiles. Some rather massive API incompatabilities, primarily because of the difficulty of coherence among competing stores.
1740
        # but neither should have added data:
1741
        self.assertEqual([[], [], [], []], self.caught_entries)
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
1742
2592.3.17 by Robert Collins
Add add_version(s) to KnitGraphIndex, completing the required api for KnitVersionedFile.
1743
    def test_add_version_different_dup(self):
2592.3.19 by Robert Collins
Change KnitGraphIndex from returning data to performing a callback on insertions.
1744
        index = self.two_graph_index(deltas=True, catch_adds=True)
2592.3.17 by Robert Collins
Add add_version(s) to KnitGraphIndex, completing the required api for KnitVersionedFile.
1745
        # change options
6729.7.2 by Jelmer Vernooij
Finish move.
1746
        self.assertRaises(KnitCorrupt, index.add_records,
7143.15.2 by Jelmer Vernooij
Run autopep8.
1747
                          [((b'tip',), b'line-delta', (None, 0, 100), [(b'parent',)])])
6729.7.2 by Jelmer Vernooij
Finish move.
1748
        self.assertRaises(KnitCorrupt, index.add_records,
7143.15.2 by Jelmer Vernooij
Run autopep8.
1749
                          [((b'tip',), b'fulltext', (None, 0, 100), [(b'parent',)])])
2592.3.17 by Robert Collins
Add add_version(s) to KnitGraphIndex, completing the required api for KnitVersionedFile.
1750
        # parents
6729.7.2 by Jelmer Vernooij
Finish move.
1751
        self.assertRaises(KnitCorrupt, index.add_records,
7143.15.2 by Jelmer Vernooij
Run autopep8.
1752
                          [((b'tip',), b'fulltext,no-eol', (None, 0, 100), [])])
2592.3.19 by Robert Collins
Change KnitGraphIndex from returning data to performing a callback on insertions.
1753
        self.assertEqual([], self.caught_entries)
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
1754
2592.3.17 by Robert Collins
Add add_version(s) to KnitGraphIndex, completing the required api for KnitVersionedFile.
1755
    def test_add_versions_nodeltas(self):
2592.3.19 by Robert Collins
Change KnitGraphIndex from returning data to performing a callback on insertions.
1756
        index = self.two_graph_index(catch_adds=True)
3350.6.4 by Robert Collins
First cut at pluralised VersionedFiles. Some rather massive API incompatabilities, primarily because of the difficulty of coherence among competing stores.
1757
        index.add_records([
7143.15.2 by Jelmer Vernooij
Run autopep8.
1758
            ((b'new',), b'fulltext,no-eol', (None, 50, 60), [(b'separate',)]),
1759
            ((b'new2',), b'fulltext', (None, 0, 6), [(b'new',)]),
1760
            ])
6973.14.2 by Jelmer Vernooij
Fix some knit tests.
1761
        self.assertEqual([((b'new', ), b'N50 60', (((b'separate',),),)),
7143.15.2 by Jelmer Vernooij
Run autopep8.
1762
                          ((b'new2', ), b' 0 6', (((b'new',),),))],
1763
                         sorted(self.caught_entries[0]))
2592.3.19 by Robert Collins
Change KnitGraphIndex from returning data to performing a callback on insertions.
1764
        self.assertEqual(1, len(self.caught_entries))
2592.3.17 by Robert Collins
Add add_version(s) to KnitGraphIndex, completing the required api for KnitVersionedFile.
1765
1766
    def test_add_versions_deltas(self):
2592.3.19 by Robert Collins
Change KnitGraphIndex from returning data to performing a callback on insertions.
1767
        index = self.two_graph_index(deltas=True, catch_adds=True)
3350.6.4 by Robert Collins
First cut at pluralised VersionedFiles. Some rather massive API incompatabilities, primarily because of the difficulty of coherence among competing stores.
1768
        index.add_records([
7143.15.2 by Jelmer Vernooij
Run autopep8.
1769
            ((b'new',), b'fulltext,no-eol', (None, 50, 60), [(b'separate',)]),
1770
            ((b'new2',), b'line-delta', (None, 0, 6), [(b'new',)]),
1771
            ])
6973.14.2 by Jelmer Vernooij
Fix some knit tests.
1772
        self.assertEqual([((b'new', ), b'N50 60', (((b'separate',),), ())),
7143.15.2 by Jelmer Vernooij
Run autopep8.
1773
                          ((b'new2', ), b' 0 6', (((b'new',),), ((b'new',),), ))],
1774
                         sorted(self.caught_entries[0]))
2592.3.19 by Robert Collins
Change KnitGraphIndex from returning data to performing a callback on insertions.
1775
        self.assertEqual(1, len(self.caught_entries))
2592.3.17 by Robert Collins
Add add_version(s) to KnitGraphIndex, completing the required api for KnitVersionedFile.
1776
1777
    def test_add_versions_delta_not_delta_index(self):
2592.3.19 by Robert Collins
Change KnitGraphIndex from returning data to performing a callback on insertions.
1778
        index = self.two_graph_index(catch_adds=True)
6729.7.2 by Jelmer Vernooij
Finish move.
1779
        self.assertRaises(KnitCorrupt, index.add_records,
7143.15.2 by Jelmer Vernooij
Run autopep8.
1780
                          [((b'new',), b'no-eol,line-delta', (None, 0, 100), [(b'parent',)])])
2592.3.19 by Robert Collins
Change KnitGraphIndex from returning data to performing a callback on insertions.
1781
        self.assertEqual([], self.caught_entries)
2592.3.17 by Robert Collins
Add add_version(s) to KnitGraphIndex, completing the required api for KnitVersionedFile.
1782
2841.2.1 by Robert Collins
* Commit no longer checks for new text keys during insertion when the
1783
    def test_add_versions_random_id_accepted(self):
1784
        index = self.two_graph_index(catch_adds=True)
3350.6.4 by Robert Collins
First cut at pluralised VersionedFiles. Some rather massive API incompatabilities, primarily because of the difficulty of coherence among competing stores.
1785
        index.add_records([], random_id=True)
2841.2.1 by Robert Collins
* Commit no longer checks for new text keys during insertion when the
1786
2592.3.17 by Robert Collins
Add add_version(s) to KnitGraphIndex, completing the required api for KnitVersionedFile.
1787
    def test_add_versions_same_dup(self):
2592.3.19 by Robert Collins
Change KnitGraphIndex from returning data to performing a callback on insertions.
1788
        index = self.two_graph_index(catch_adds=True)
2592.3.17 by Robert Collins
Add add_version(s) to KnitGraphIndex, completing the required api for KnitVersionedFile.
1789
        # options can be spelt two different ways
6973.14.2 by Jelmer Vernooij
Fix some knit tests.
1790
        index.add_records([((b'tip',), b'fulltext,no-eol', (None, 0, 100),
7143.15.2 by Jelmer Vernooij
Run autopep8.
1791
                            [(b'parent',)])])
6973.14.2 by Jelmer Vernooij
Fix some knit tests.
1792
        index.add_records([((b'tip',), b'no-eol,fulltext', (None, 0, 100),
7143.15.2 by Jelmer Vernooij
Run autopep8.
1793
                            [(b'parent',)])])
3350.6.4 by Robert Collins
First cut at pluralised VersionedFiles. Some rather massive API incompatabilities, primarily because of the difficulty of coherence among competing stores.
1794
        # position/length are ignored (because each pack could have fulltext or
1795
        # delta, and be at a different position.
6973.14.2 by Jelmer Vernooij
Fix some knit tests.
1796
        index.add_records([((b'tip',), b'fulltext,no-eol', (None, 50, 100),
7143.15.2 by Jelmer Vernooij
Run autopep8.
1797
                            [(b'parent',)])])
6973.14.2 by Jelmer Vernooij
Fix some knit tests.
1798
        index.add_records([((b'tip',), b'fulltext,no-eol', (None, 0, 1000),
7143.15.2 by Jelmer Vernooij
Run autopep8.
1799
                            [(b'parent',)])])
2592.3.19 by Robert Collins
Change KnitGraphIndex from returning data to performing a callback on insertions.
1800
        # but neither should have added data.
3350.6.4 by Robert Collins
First cut at pluralised VersionedFiles. Some rather massive API incompatabilities, primarily because of the difficulty of coherence among competing stores.
1801
        self.assertEqual([[], [], [], []], self.caught_entries)
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
1802
2592.3.17 by Robert Collins
Add add_version(s) to KnitGraphIndex, completing the required api for KnitVersionedFile.
1803
    def test_add_versions_different_dup(self):
2592.3.19 by Robert Collins
Change KnitGraphIndex from returning data to performing a callback on insertions.
1804
        index = self.two_graph_index(deltas=True, catch_adds=True)
2592.3.17 by Robert Collins
Add add_version(s) to KnitGraphIndex, completing the required api for KnitVersionedFile.
1805
        # change options
6729.7.2 by Jelmer Vernooij
Finish move.
1806
        self.assertRaises(KnitCorrupt, index.add_records,
7143.15.2 by Jelmer Vernooij
Run autopep8.
1807
                          [((b'tip',), b'line-delta', (None, 0, 100), [(b'parent',)])])
6729.7.2 by Jelmer Vernooij
Finish move.
1808
        self.assertRaises(KnitCorrupt, index.add_records,
7143.15.2 by Jelmer Vernooij
Run autopep8.
1809
                          [((b'tip',), b'fulltext', (None, 0, 100), [(b'parent',)])])
2592.3.17 by Robert Collins
Add add_version(s) to KnitGraphIndex, completing the required api for KnitVersionedFile.
1810
        # parents
6729.7.2 by Jelmer Vernooij
Finish move.
1811
        self.assertRaises(KnitCorrupt, index.add_records,
7143.15.2 by Jelmer Vernooij
Run autopep8.
1812
                          [((b'tip',), b'fulltext,no-eol', (None, 0, 100), [])])
2592.3.17 by Robert Collins
Add add_version(s) to KnitGraphIndex, completing the required api for KnitVersionedFile.
1813
        # change options in the second record
6729.7.2 by Jelmer Vernooij
Finish move.
1814
        self.assertRaises(KnitCorrupt, index.add_records,
7143.15.2 by Jelmer Vernooij
Run autopep8.
1815
                          [((b'tip',), b'fulltext,no-eol', (None, 0, 100), [(b'parent',)]),
1816
                           ((b'tip',), b'line-delta', (None, 0, 100), [(b'parent',)])])
2592.3.19 by Robert Collins
Change KnitGraphIndex from returning data to performing a callback on insertions.
1817
        self.assertEqual([], self.caught_entries)
2592.3.34 by Robert Collins
Rough unfactored support for parentless KnitGraphIndexs.
1818
4011.5.2 by Andrew Bennetts
Add more tests, improve existing tests, add GraphIndex._external_references()
1819
    def make_g_index_missing_compression_parent(self):
1820
        graph_index = self.make_g_index('missing_comp', 2,
7143.15.2 by Jelmer Vernooij
Run autopep8.
1821
                                        [((b'tip', ), b' 100 78',
1822
                                          ([(b'missing-parent', ), (b'ghost', )], [(b'missing-parent', )]))])
4011.5.2 by Andrew Bennetts
Add more tests, improve existing tests, add GraphIndex._external_references()
1823
        return graph_index
4032.1.2 by John Arbash Meinel
Track down a few more files that have trailing whitespace.
1824
4257.4.14 by Andrew Bennetts
Add a unit test for _KnitGraphIndex.get_missing_parents, fix bug that it reveals.
1825
    def make_g_index_missing_parent(self):
1826
        graph_index = self.make_g_index('missing_parent', 2,
7143.15.2 by Jelmer Vernooij
Run autopep8.
1827
                                        [((b'parent', ), b' 100 78', ([], [])),
1828
                                         ((b'tip', ), b' 100 78',
1829
                                            ([(b'parent', ), (b'missing-parent', )], [(b'parent', )])),
1830
                                         ])
4257.4.14 by Andrew Bennetts
Add a unit test for _KnitGraphIndex.get_missing_parents, fix bug that it reveals.
1831
        return graph_index
1832
4011.5.2 by Andrew Bennetts
Add more tests, improve existing tests, add GraphIndex._external_references()
1833
    def make_g_index_no_external_refs(self):
1834
        graph_index = self.make_g_index('no_external_refs', 2,
7143.15.2 by Jelmer Vernooij
Run autopep8.
1835
                                        [((b'rev', ), b' 100 78',
1836
                                          ([(b'parent', ), (b'ghost', )], []))])
4011.5.2 by Andrew Bennetts
Add more tests, improve existing tests, add GraphIndex._external_references()
1837
        return graph_index
1838
4011.5.1 by Andrew Bennetts
Start to add _add_unvalidated_index/get_missing_compression_parents methods to _KnitGraphIndex.
1839
    def test_add_good_unvalidated_index(self):
4011.5.2 by Andrew Bennetts
Add more tests, improve existing tests, add GraphIndex._external_references()
1840
        unvalidated = self.make_g_index_no_external_refs()
1841
        combined = CombinedGraphIndex([unvalidated])
4011.5.11 by Robert Collins
Polish the KnitVersionedFiles.scan_unvalidated_index api.
1842
        index = _KnitGraphIndex(combined, lambda: True, deltas=True)
4011.5.7 by Andrew Bennetts
Remove leading underscore from _scan_unvalidate_index, explicitly NotImplementedError it for _KndxIndex.
1843
        index.scan_unvalidated_index(unvalidated)
4011.5.1 by Andrew Bennetts
Start to add _add_unvalidated_index/get_missing_compression_parents methods to _KnitGraphIndex.
1844
        self.assertEqual(frozenset(), index.get_missing_compression_parents())
1845
4257.4.14 by Andrew Bennetts
Add a unit test for _KnitGraphIndex.get_missing_parents, fix bug that it reveals.
1846
    def test_add_missing_compression_parent_unvalidated_index(self):
4011.5.2 by Andrew Bennetts
Add more tests, improve existing tests, add GraphIndex._external_references()
1847
        unvalidated = self.make_g_index_missing_compression_parent()
1848
        combined = CombinedGraphIndex([unvalidated])
4011.5.11 by Robert Collins
Polish the KnitVersionedFiles.scan_unvalidated_index api.
1849
        index = _KnitGraphIndex(combined, lambda: True, deltas=True)
4011.5.7 by Andrew Bennetts
Remove leading underscore from _scan_unvalidate_index, explicitly NotImplementedError it for _KndxIndex.
1850
        index.scan_unvalidated_index(unvalidated)
4011.5.6 by Andrew Bennetts
Make sure it's not possible to commit a pack write group when any versioned file has missing compression parents.
1851
        # This also checks that its only the compression parent that is
1852
        # examined, otherwise 'ghost' would also be reported as a missing
1853
        # parent.
4011.5.1 by Andrew Bennetts
Start to add _add_unvalidated_index/get_missing_compression_parents methods to _KnitGraphIndex.
1854
        self.assertEqual(
6973.14.2 by Jelmer Vernooij
Fix some knit tests.
1855
            frozenset([(b'missing-parent',)]),
4011.5.2 by Andrew Bennetts
Add more tests, improve existing tests, add GraphIndex._external_references()
1856
            index.get_missing_compression_parents())
4011.5.1 by Andrew Bennetts
Start to add _add_unvalidated_index/get_missing_compression_parents methods to _KnitGraphIndex.
1857
4257.4.14 by Andrew Bennetts
Add a unit test for _KnitGraphIndex.get_missing_parents, fix bug that it reveals.
1858
    def test_add_missing_noncompression_parent_unvalidated_index(self):
1859
        unvalidated = self.make_g_index_missing_parent()
1860
        combined = CombinedGraphIndex([unvalidated])
1861
        index = _KnitGraphIndex(combined, lambda: True, deltas=True,
7143.15.2 by Jelmer Vernooij
Run autopep8.
1862
                                track_external_parent_refs=True)
4257.4.14 by Andrew Bennetts
Add a unit test for _KnitGraphIndex.get_missing_parents, fix bug that it reveals.
1863
        index.scan_unvalidated_index(unvalidated)
1864
        self.assertEqual(
6973.14.2 by Jelmer Vernooij
Fix some knit tests.
1865
            frozenset([(b'missing-parent',)]), index.get_missing_parents())
4257.4.14 by Andrew Bennetts
Add a unit test for _KnitGraphIndex.get_missing_parents, fix bug that it reveals.
1866
4257.4.15 by Andrew Bennetts
Add another test for _KnitGraphIndex.get_missing_parents().
1867
    def test_track_external_parent_refs(self):
1868
        g_index = self.make_g_index('empty', 2, [])
1869
        combined = CombinedGraphIndex([g_index])
1870
        index = _KnitGraphIndex(combined, lambda: True, deltas=True,
7143.15.2 by Jelmer Vernooij
Run autopep8.
1871
                                add_callback=self.catch_add, track_external_parent_refs=True)
4257.4.15 by Andrew Bennetts
Add another test for _KnitGraphIndex.get_missing_parents().
1872
        self.caught_entries = []
1873
        index.add_records([
6973.11.7 by Jelmer Vernooij
Fix more tests.
1874
            ((b'new-key',), b'fulltext,no-eol', (None, 50, 60),
1875
             [(b'parent-1',), (b'parent-2',)])])
4257.4.15 by Andrew Bennetts
Add another test for _KnitGraphIndex.get_missing_parents().
1876
        self.assertEqual(
6973.11.7 by Jelmer Vernooij
Fix more tests.
1877
            frozenset([(b'parent-1',), (b'parent-2',)]),
4257.4.15 by Andrew Bennetts
Add another test for _KnitGraphIndex.get_missing_parents().
1878
            index.get_missing_parents())
1879
4011.5.1 by Andrew Bennetts
Start to add _add_unvalidated_index/get_missing_compression_parents methods to _KnitGraphIndex.
1880
    def test_add_unvalidated_index_with_present_external_references(self):
1881
        index = self.two_graph_index(deltas=True)
4011.5.10 by Andrew Bennetts
Replace XXX with better comment.
1882
        # Ugly hack to get at one of the underlying GraphIndex objects that
1883
        # two_graph_index built.
1884
        unvalidated = index._graph_index._indices[1]
1885
        # 'parent' is an external ref of _indices[1] (unvalidated), but is
1886
        # present in _indices[0].
4011.5.7 by Andrew Bennetts
Remove leading underscore from _scan_unvalidate_index, explicitly NotImplementedError it for _KndxIndex.
1887
        index.scan_unvalidated_index(unvalidated)
4011.5.1 by Andrew Bennetts
Start to add _add_unvalidated_index/get_missing_compression_parents methods to _KnitGraphIndex.
1888
        self.assertEqual(frozenset(), index.get_missing_compression_parents())
1889
4011.5.2 by Andrew Bennetts
Add more tests, improve existing tests, add GraphIndex._external_references()
1890
    def make_new_missing_parent_g_index(self, name):
6973.11.7 by Jelmer Vernooij
Fix more tests.
1891
        missing_parent = name.encode('ascii') + b'-missing-parent'
4011.5.2 by Andrew Bennetts
Add more tests, improve existing tests, add GraphIndex._external_references()
1892
        graph_index = self.make_g_index(name, 2,
7143.15.2 by Jelmer Vernooij
Run autopep8.
1893
                                        [((name.encode('ascii') + b'tip', ), b' 100 78',
1894
                                          ([(missing_parent, ), (b'ghost', )], [(missing_parent, )]))])
4011.5.2 by Andrew Bennetts
Add more tests, improve existing tests, add GraphIndex._external_references()
1895
        return graph_index
1896
1897
    def test_add_mulitiple_unvalidated_indices_with_missing_parents(self):
1898
        g_index_1 = self.make_new_missing_parent_g_index('one')
1899
        g_index_2 = self.make_new_missing_parent_g_index('two')
1900
        combined = CombinedGraphIndex([g_index_1, g_index_2])
4011.5.11 by Robert Collins
Polish the KnitVersionedFiles.scan_unvalidated_index api.
1901
        index = _KnitGraphIndex(combined, lambda: True, deltas=True)
4011.5.7 by Andrew Bennetts
Remove leading underscore from _scan_unvalidate_index, explicitly NotImplementedError it for _KndxIndex.
1902
        index.scan_unvalidated_index(g_index_1)
1903
        index.scan_unvalidated_index(g_index_2)
4011.5.2 by Andrew Bennetts
Add more tests, improve existing tests, add GraphIndex._external_references()
1904
        self.assertEqual(
6973.11.7 by Jelmer Vernooij
Fix more tests.
1905
            frozenset([(b'one-missing-parent',), (b'two-missing-parent',)]),
4011.5.2 by Andrew Bennetts
Add more tests, improve existing tests, add GraphIndex._external_references()
1906
            index.get_missing_compression_parents())
1907
1908
    def test_add_mulitiple_unvalidated_indices_with_mutual_dependencies(self):
1909
        graph_index_a = self.make_g_index('one', 2,
7143.15.2 by Jelmer Vernooij
Run autopep8.
1910
                                          [((b'parent-one', ), b' 100 78', ([(b'non-compression-parent',)], [])),
1911
                                           ((b'child-of-two', ), b' 100 78',
1912
                                              ([(b'parent-two',)], [(b'parent-two',)]))])
4011.5.2 by Andrew Bennetts
Add more tests, improve existing tests, add GraphIndex._external_references()
1913
        graph_index_b = self.make_g_index('two', 2,
7143.15.2 by Jelmer Vernooij
Run autopep8.
1914
                                          [((b'parent-two', ), b' 100 78', ([(b'non-compression-parent',)], [])),
1915
                                           ((b'child-of-one', ), b' 100 78',
1916
                                              ([(b'parent-one',)], [(b'parent-one',)]))])
4011.5.2 by Andrew Bennetts
Add more tests, improve existing tests, add GraphIndex._external_references()
1917
        combined = CombinedGraphIndex([graph_index_a, graph_index_b])
4011.5.11 by Robert Collins
Polish the KnitVersionedFiles.scan_unvalidated_index api.
1918
        index = _KnitGraphIndex(combined, lambda: True, deltas=True)
4011.5.7 by Andrew Bennetts
Remove leading underscore from _scan_unvalidate_index, explicitly NotImplementedError it for _KndxIndex.
1919
        index.scan_unvalidated_index(graph_index_a)
1920
        index.scan_unvalidated_index(graph_index_b)
4011.5.2 by Andrew Bennetts
Add more tests, improve existing tests, add GraphIndex._external_references()
1921
        self.assertEqual(
1922
            frozenset([]), index.get_missing_compression_parents())
4032.1.2 by John Arbash Meinel
Track down a few more files that have trailing whitespace.
1923
4011.5.2 by Andrew Bennetts
Add more tests, improve existing tests, add GraphIndex._external_references()
1924
2592.3.34 by Robert Collins
Rough unfactored support for parentless KnitGraphIndexs.
1925
class TestNoParentsGraphIndexKnit(KnitTests):
3350.6.4 by Robert Collins
First cut at pluralised VersionedFiles. Some rather massive API incompatabilities, primarily because of the difficulty of coherence among competing stores.
1926
    """Tests for knits using _KnitGraphIndex with no parents."""
2592.3.34 by Robert Collins
Rough unfactored support for parentless KnitGraphIndexs.
1927
1928
    def make_g_index(self, name, ref_lists=0, nodes=[]):
1929
        builder = GraphIndexBuilder(ref_lists)
1930
        for node, references in nodes:
1931
            builder.add_node(node, references)
1932
        stream = builder.finish()
1933
        trans = self.get_transport()
2890.2.1 by Robert Collins
* ``bzrlib.index.GraphIndex`` now requires a size parameter to the
1934
        size = trans.put_file(name, stream)
1935
        return GraphIndex(trans, name, size)
2592.3.34 by Robert Collins
Rough unfactored support for parentless KnitGraphIndexs.
1936
4011.5.11 by Robert Collins
Polish the KnitVersionedFiles.scan_unvalidated_index api.
1937
    def test_add_good_unvalidated_index(self):
1938
        unvalidated = self.make_g_index('unvalidated')
1939
        combined = CombinedGraphIndex([unvalidated])
1940
        index = _KnitGraphIndex(combined, lambda: True, parents=False)
1941
        index.scan_unvalidated_index(unvalidated)
1942
        self.assertEqual(frozenset(),
7143.15.2 by Jelmer Vernooij
Run autopep8.
1943
                         index.get_missing_compression_parents())
4011.5.11 by Robert Collins
Polish the KnitVersionedFiles.scan_unvalidated_index api.
1944
2592.3.34 by Robert Collins
Rough unfactored support for parentless KnitGraphIndexs.
1945
    def test_parents_deltas_incompatible(self):
1946
        index = CombinedGraphIndex([])
7143.15.2 by Jelmer Vernooij
Run autopep8.
1947
        self.assertRaises(knit.KnitError, _KnitGraphIndex, lambda: True,
1948
                          index, deltas=True, parents=False)
2592.3.34 by Robert Collins
Rough unfactored support for parentless KnitGraphIndexs.
1949
1950
    def two_graph_index(self, catch_adds=False):
1951
        """Build a two-graph index.
1952
1953
        :param deltas: If true, use underlying indices with two node-ref
1954
            lists and 'parent' set to a delta-compressed against tail.
1955
        """
1956
        # put several versions in the index.
1957
        index1 = self.make_g_index('1', 0, [
6973.14.2 by Jelmer Vernooij
Fix some knit tests.
1958
            ((b'tip', ), b'N0 100'),
1959
            ((b'tail', ), b'')])
2592.3.34 by Robert Collins
Rough unfactored support for parentless KnitGraphIndexs.
1960
        index2 = self.make_g_index('2', 0, [
6973.14.2 by Jelmer Vernooij
Fix some knit tests.
1961
            ((b'parent', ), b' 100 78'),
1962
            ((b'separate', ), b'')])
2592.3.34 by Robert Collins
Rough unfactored support for parentless KnitGraphIndexs.
1963
        combined_index = CombinedGraphIndex([index1, index2])
1964
        if catch_adds:
1965
            self.combined_index = combined_index
1966
            self.caught_entries = []
1967
            add_callback = self.catch_add
1968
        else:
1969
            add_callback = None
7143.15.2 by Jelmer Vernooij
Run autopep8.
1970
        return _KnitGraphIndex(combined_index, lambda: True, parents=False,
1971
                               add_callback=add_callback)
2592.3.34 by Robert Collins
Rough unfactored support for parentless KnitGraphIndexs.
1972
3350.6.4 by Robert Collins
First cut at pluralised VersionedFiles. Some rather massive API incompatabilities, primarily because of the difficulty of coherence among competing stores.
1973
    def test_keys(self):
1974
        index = self.two_graph_index()
6985 by Jelmer Vernooij
Merge lp:~jelmer/brz/python3-weave-fmt.
1975
        self.assertEqual({(b'tail',), (b'tip',), (b'parent',), (b'separate',)},
7143.15.2 by Jelmer Vernooij
Run autopep8.
1976
                         set(index.keys()))
2592.3.34 by Robert Collins
Rough unfactored support for parentless KnitGraphIndexs.
1977
1978
    def test_get_position(self):
1979
        index = self.two_graph_index()
3350.6.4 by Robert Collins
First cut at pluralised VersionedFiles. Some rather massive API incompatabilities, primarily because of the difficulty of coherence among competing stores.
1980
        self.assertEqual((index._graph_index._indices[0], 0, 100),
7143.15.2 by Jelmer Vernooij
Run autopep8.
1981
                         index.get_position((b'tip',)))
3350.6.4 by Robert Collins
First cut at pluralised VersionedFiles. Some rather massive API incompatabilities, primarily because of the difficulty of coherence among competing stores.
1982
        self.assertEqual((index._graph_index._indices[1], 100, 78),
7143.15.2 by Jelmer Vernooij
Run autopep8.
1983
                         index.get_position((b'parent',)))
2592.3.34 by Robert Collins
Rough unfactored support for parentless KnitGraphIndexs.
1984
1985
    def test_get_method(self):
1986
        index = self.two_graph_index()
6973.14.2 by Jelmer Vernooij
Fix some knit tests.
1987
        self.assertEqual('fulltext', index.get_method((b'tip',)))
1988
        self.assertEqual([b'fulltext'], index.get_options((b'parent',)))
2592.3.34 by Robert Collins
Rough unfactored support for parentless KnitGraphIndexs.
1989
1990
    def test_get_options(self):
1991
        index = self.two_graph_index()
7143.15.2 by Jelmer Vernooij
Run autopep8.
1992
        self.assertEqual([b'fulltext', b'no-eol'],
1993
                         index.get_options((b'tip',)))
6973.14.2 by Jelmer Vernooij
Fix some knit tests.
1994
        self.assertEqual([b'fulltext'], index.get_options((b'parent',)))
3350.6.4 by Robert Collins
First cut at pluralised VersionedFiles. Some rather massive API incompatabilities, primarily because of the difficulty of coherence among competing stores.
1995
1996
    def test_get_parent_map(self):
1997
        index = self.two_graph_index()
7143.15.2 by Jelmer Vernooij
Run autopep8.
1998
        self.assertEqual({(b'parent',): None},
1999
                         index.get_parent_map([(b'parent',), (b'ghost',)]))
2592.3.34 by Robert Collins
Rough unfactored support for parentless KnitGraphIndexs.
2000
2001
    def catch_add(self, entries):
2002
        self.caught_entries.append(entries)
2003
2004
    def test_add_no_callback_errors(self):
2005
        index = self.two_graph_index()
3350.6.4 by Robert Collins
First cut at pluralised VersionedFiles. Some rather massive API incompatabilities, primarily because of the difficulty of coherence among competing stores.
2006
        self.assertRaises(errors.ReadOnlyError, index.add_records,
7143.15.2 by Jelmer Vernooij
Run autopep8.
2007
                          [((b'new',), b'fulltext,no-eol', (None, 50, 60), [(b'separate',)])])
2592.3.34 by Robert Collins
Rough unfactored support for parentless KnitGraphIndexs.
2008
2009
    def test_add_version_smoke(self):
2010
        index = self.two_graph_index(catch_adds=True)
7143.15.2 by Jelmer Vernooij
Run autopep8.
2011
        index.add_records(
2012
            [((b'new',), b'fulltext,no-eol', (None, 50, 60), [])])
6973.14.2 by Jelmer Vernooij
Fix some knit tests.
2013
        self.assertEqual([[((b'new', ), b'N50 60')]],
7143.15.2 by Jelmer Vernooij
Run autopep8.
2014
                         self.caught_entries)
2592.3.34 by Robert Collins
Rough unfactored support for parentless KnitGraphIndexs.
2015
2016
    def test_add_version_delta_not_delta_index(self):
2017
        index = self.two_graph_index(catch_adds=True)
6729.7.2 by Jelmer Vernooij
Finish move.
2018
        self.assertRaises(KnitCorrupt, index.add_records,
7143.15.2 by Jelmer Vernooij
Run autopep8.
2019
                          [((b'new',), b'no-eol,line-delta', (None, 0, 100), [])])
2592.3.34 by Robert Collins
Rough unfactored support for parentless KnitGraphIndexs.
2020
        self.assertEqual([], self.caught_entries)
2021
2022
    def test_add_version_same_dup(self):
2023
        index = self.two_graph_index(catch_adds=True)
2024
        # options can be spelt two different ways
7143.15.2 by Jelmer Vernooij
Run autopep8.
2025
        index.add_records(
2026
            [((b'tip',), b'fulltext,no-eol', (None, 0, 100), [])])
2027
        index.add_records(
2028
            [((b'tip',), b'no-eol,fulltext', (None, 0, 100), [])])
3350.6.4 by Robert Collins
First cut at pluralised VersionedFiles. Some rather massive API incompatabilities, primarily because of the difficulty of coherence among competing stores.
2029
        # position/length are ignored (because each pack could have fulltext or
2030
        # delta, and be at a different position.
7143.15.2 by Jelmer Vernooij
Run autopep8.
2031
        index.add_records(
2032
            [((b'tip',), b'fulltext,no-eol', (None, 50, 100), [])])
2033
        index.add_records(
2034
            [((b'tip',), b'fulltext,no-eol', (None, 0, 1000), [])])
2592.3.34 by Robert Collins
Rough unfactored support for parentless KnitGraphIndexs.
2035
        # but neither should have added data.
3350.6.4 by Robert Collins
First cut at pluralised VersionedFiles. Some rather massive API incompatabilities, primarily because of the difficulty of coherence among competing stores.
2036
        self.assertEqual([[], [], [], []], self.caught_entries)
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
2037
2592.3.34 by Robert Collins
Rough unfactored support for parentless KnitGraphIndexs.
2038
    def test_add_version_different_dup(self):
2039
        index = self.two_graph_index(catch_adds=True)
2040
        # change options
6729.7.2 by Jelmer Vernooij
Finish move.
2041
        self.assertRaises(KnitCorrupt, index.add_records,
7143.15.2 by Jelmer Vernooij
Run autopep8.
2042
                          [((b'tip',), b'no-eol,line-delta', (None, 0, 100), [])])
2043
        self.assertRaises(KnitCorrupt, index.add_records,
2044
                          [((b'tip',), b'line-delta,no-eol', (None, 0, 100), [])])
2045
        self.assertRaises(KnitCorrupt, index.add_records,
2046
                          [((b'tip',), b'fulltext', (None, 0, 100), [])])
2592.3.34 by Robert Collins
Rough unfactored support for parentless KnitGraphIndexs.
2047
        # parents
6729.7.2 by Jelmer Vernooij
Finish move.
2048
        self.assertRaises(KnitCorrupt, index.add_records,
7143.15.2 by Jelmer Vernooij
Run autopep8.
2049
                          [((b'tip',), b'fulltext,no-eol', (None, 0, 100), [(b'parent',)])])
2592.3.34 by Robert Collins
Rough unfactored support for parentless KnitGraphIndexs.
2050
        self.assertEqual([], self.caught_entries)
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
2051
2592.3.34 by Robert Collins
Rough unfactored support for parentless KnitGraphIndexs.
2052
    def test_add_versions(self):
2053
        index = self.two_graph_index(catch_adds=True)
3350.6.4 by Robert Collins
First cut at pluralised VersionedFiles. Some rather massive API incompatabilities, primarily because of the difficulty of coherence among competing stores.
2054
        index.add_records([
7143.15.2 by Jelmer Vernooij
Run autopep8.
2055
            ((b'new',), b'fulltext,no-eol', (None, 50, 60), []),
2056
            ((b'new2',), b'fulltext', (None, 0, 6), []),
2057
            ])
6973.14.2 by Jelmer Vernooij
Fix some knit tests.
2058
        self.assertEqual([((b'new', ), b'N50 60'), ((b'new2', ), b' 0 6')],
7143.15.2 by Jelmer Vernooij
Run autopep8.
2059
                         sorted(self.caught_entries[0]))
2592.3.34 by Robert Collins
Rough unfactored support for parentless KnitGraphIndexs.
2060
        self.assertEqual(1, len(self.caught_entries))
2061
2062
    def test_add_versions_delta_not_delta_index(self):
2063
        index = self.two_graph_index(catch_adds=True)
6729.7.2 by Jelmer Vernooij
Finish move.
2064
        self.assertRaises(KnitCorrupt, index.add_records,
7143.15.2 by Jelmer Vernooij
Run autopep8.
2065
                          [((b'new',), b'no-eol,line-delta', (None, 0, 100), [(b'parent',)])])
2592.3.34 by Robert Collins
Rough unfactored support for parentless KnitGraphIndexs.
2066
        self.assertEqual([], self.caught_entries)
2067
2068
    def test_add_versions_parents_not_parents_index(self):
2069
        index = self.two_graph_index(catch_adds=True)
6729.7.2 by Jelmer Vernooij
Finish move.
2070
        self.assertRaises(KnitCorrupt, index.add_records,
7143.15.2 by Jelmer Vernooij
Run autopep8.
2071
                          [((b'new',), b'no-eol,fulltext', (None, 0, 100), [(b'parent',)])])
2592.3.34 by Robert Collins
Rough unfactored support for parentless KnitGraphIndexs.
2072
        self.assertEqual([], self.caught_entries)
2073
2841.2.1 by Robert Collins
* Commit no longer checks for new text keys during insertion when the
2074
    def test_add_versions_random_id_accepted(self):
2075
        index = self.two_graph_index(catch_adds=True)
3350.6.4 by Robert Collins
First cut at pluralised VersionedFiles. Some rather massive API incompatabilities, primarily because of the difficulty of coherence among competing stores.
2076
        index.add_records([], random_id=True)
2841.2.1 by Robert Collins
* Commit no longer checks for new text keys during insertion when the
2077
2592.3.34 by Robert Collins
Rough unfactored support for parentless KnitGraphIndexs.
2078
    def test_add_versions_same_dup(self):
2079
        index = self.two_graph_index(catch_adds=True)
2080
        # options can be spelt two different ways
7143.15.2 by Jelmer Vernooij
Run autopep8.
2081
        index.add_records(
2082
            [((b'tip',), b'fulltext,no-eol', (None, 0, 100), [])])
2083
        index.add_records(
2084
            [((b'tip',), b'no-eol,fulltext', (None, 0, 100), [])])
3350.6.4 by Robert Collins
First cut at pluralised VersionedFiles. Some rather massive API incompatabilities, primarily because of the difficulty of coherence among competing stores.
2085
        # position/length are ignored (because each pack could have fulltext or
2086
        # delta, and be at a different position.
7143.15.2 by Jelmer Vernooij
Run autopep8.
2087
        index.add_records(
2088
            [((b'tip',), b'fulltext,no-eol', (None, 50, 100), [])])
2089
        index.add_records(
2090
            [((b'tip',), b'fulltext,no-eol', (None, 0, 1000), [])])
2592.3.34 by Robert Collins
Rough unfactored support for parentless KnitGraphIndexs.
2091
        # but neither should have added data.
3350.6.4 by Robert Collins
First cut at pluralised VersionedFiles. Some rather massive API incompatabilities, primarily because of the difficulty of coherence among competing stores.
2092
        self.assertEqual([[], [], [], []], self.caught_entries)
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
2093
2592.3.34 by Robert Collins
Rough unfactored support for parentless KnitGraphIndexs.
2094
    def test_add_versions_different_dup(self):
2095
        index = self.two_graph_index(catch_adds=True)
2096
        # change options
6729.7.2 by Jelmer Vernooij
Finish move.
2097
        self.assertRaises(KnitCorrupt, index.add_records,
7143.15.2 by Jelmer Vernooij
Run autopep8.
2098
                          [((b'tip',), b'no-eol,line-delta', (None, 0, 100), [])])
2099
        self.assertRaises(KnitCorrupt, index.add_records,
2100
                          [((b'tip',), b'line-delta,no-eol', (None, 0, 100), [])])
2101
        self.assertRaises(KnitCorrupt, index.add_records,
2102
                          [((b'tip',), b'fulltext', (None, 0, 100), [])])
2592.3.34 by Robert Collins
Rough unfactored support for parentless KnitGraphIndexs.
2103
        # parents
6729.7.2 by Jelmer Vernooij
Finish move.
2104
        self.assertRaises(KnitCorrupt, index.add_records,
7143.15.2 by Jelmer Vernooij
Run autopep8.
2105
                          [((b'tip',), b'fulltext,no-eol', (None, 0, 100), [(b'parent',)])])
2592.3.34 by Robert Collins
Rough unfactored support for parentless KnitGraphIndexs.
2106
        # change options in the second record
6729.7.2 by Jelmer Vernooij
Finish move.
2107
        self.assertRaises(KnitCorrupt, index.add_records,
7143.15.2 by Jelmer Vernooij
Run autopep8.
2108
                          [((b'tip',), b'fulltext,no-eol', (None, 0, 100), []),
2109
                           ((b'tip',), b'no-eol,line-delta', (None, 0, 100), [])])
2592.3.34 by Robert Collins
Rough unfactored support for parentless KnitGraphIndexs.
2110
        self.assertEqual([], self.caught_entries)
3350.8.1 by Robert Collins
KnitVersionedFiles.add_fallback_versioned_files exists.
2111
2112
4039.3.6 by John Arbash Meinel
Turn _split_by_prefix into a classmethod, and add direct tests.
2113
class TestKnitVersionedFiles(KnitTests):
2114
4039.3.7 by John Arbash Meinel
Some direct tests for _group_keys_for_io
2115
    def assertGroupKeysForIo(self, exp_groups, keys, non_local_keys,
2116
                             positions, _min_buffer_size=None):
2117
        kvf = self.make_test_knit()
2118
        if _min_buffer_size is None:
2119
            _min_buffer_size = knit._STREAM_MIN_BUFFER_SIZE
2120
        self.assertEqual(exp_groups, kvf._group_keys_for_io(keys,
7143.15.2 by Jelmer Vernooij
Run autopep8.
2121
                                                            non_local_keys, positions,
2122
                                                            _min_buffer_size=_min_buffer_size))
4039.3.7 by John Arbash Meinel
Some direct tests for _group_keys_for_io
2123
4039.3.6 by John Arbash Meinel
Turn _split_by_prefix into a classmethod, and add direct tests.
2124
    def assertSplitByPrefix(self, expected_map, expected_prefix_order,
2125
                            keys):
2126
        split, prefix_order = KnitVersionedFiles._split_by_prefix(keys)
2127
        self.assertEqual(expected_map, split)
2128
        self.assertEqual(expected_prefix_order, prefix_order)
2129
4039.3.7 by John Arbash Meinel
Some direct tests for _group_keys_for_io
2130
    def test__group_keys_for_io(self):
7078.6.1 by Jelmer Vernooij
Fix corrupt knit handling on Python 3.
2131
        ft_detail = ('fulltext', False)
2132
        ld_detail = ('line-delta', False)
6985 by Jelmer Vernooij
Merge lp:~jelmer/brz/python3-weave-fmt.
2133
        f_a = (b'f', b'a')
2134
        f_b = (b'f', b'b')
2135
        f_c = (b'f', b'c')
2136
        g_a = (b'g', b'a')
2137
        g_b = (b'g', b'b')
2138
        g_c = (b'g', b'c')
4039.3.7 by John Arbash Meinel
Some direct tests for _group_keys_for_io
2139
        positions = {
2140
            f_a: (ft_detail, (f_a, 0, 100), None),
2141
            f_b: (ld_detail, (f_b, 100, 21), f_a),
2142
            f_c: (ld_detail, (f_c, 180, 15), f_b),
2143
            g_a: (ft_detail, (g_a, 121, 35), None),
2144
            g_b: (ld_detail, (g_b, 156, 12), g_a),
2145
            g_c: (ld_detail, (g_c, 195, 13), g_a),
2146
            }
2147
        self.assertGroupKeysForIo([([f_a], set())],
2148
                                  [f_a], [], positions)
6619.3.12 by Jelmer Vernooij
Use 2to3 set_literal fixer.
2149
        self.assertGroupKeysForIo([([f_a], {f_a})],
4039.3.7 by John Arbash Meinel
Some direct tests for _group_keys_for_io
2150
                                  [f_a], [f_a], positions)
2151
        self.assertGroupKeysForIo([([f_a, f_b], set([]))],
2152
                                  [f_a, f_b], [], positions)
6619.3.12 by Jelmer Vernooij
Use 2to3 set_literal fixer.
2153
        self.assertGroupKeysForIo([([f_a, f_b], {f_b})],
4039.3.7 by John Arbash Meinel
Some direct tests for _group_keys_for_io
2154
                                  [f_a, f_b], [f_b], positions)
2155
        self.assertGroupKeysForIo([([f_a, f_b, g_a, g_b], set())],
2156
                                  [f_a, g_a, f_b, g_b], [], positions)
2157
        self.assertGroupKeysForIo([([f_a, f_b, g_a, g_b], set())],
2158
                                  [f_a, g_a, f_b, g_b], [], positions,
2159
                                  _min_buffer_size=150)
2160
        self.assertGroupKeysForIo([([f_a, f_b], set()), ([g_a, g_b], set())],
2161
                                  [f_a, g_a, f_b, g_b], [], positions,
2162
                                  _min_buffer_size=100)
2163
        self.assertGroupKeysForIo([([f_c], set()), ([g_b], set())],
2164
                                  [f_c, g_b], [], positions,
2165
                                  _min_buffer_size=125)
2166
        self.assertGroupKeysForIo([([g_b, f_c], set())],
2167
                                  [g_b, f_c], [], positions,
2168
                                  _min_buffer_size=125)
2169
4039.3.6 by John Arbash Meinel
Turn _split_by_prefix into a classmethod, and add direct tests.
2170
    def test__split_by_prefix(self):
6963.2.3 by Jelmer Vernooij
Fix some more tests.
2171
        self.assertSplitByPrefix({b'f': [(b'f', b'a'), (b'f', b'b')],
2172
                                  b'g': [(b'g', b'b'), (b'g', b'a')],
7143.15.2 by Jelmer Vernooij
Run autopep8.
2173
                                  }, [b'f', b'g'],
6963.2.3 by Jelmer Vernooij
Fix some more tests.
2174
                                 [(b'f', b'a'), (b'g', b'b'),
2175
                                  (b'g', b'a'), (b'f', b'b')])
2176
2177
        self.assertSplitByPrefix({b'f': [(b'f', b'a'), (b'f', b'b')],
2178
                                  b'g': [(b'g', b'b'), (b'g', b'a')],
7143.15.2 by Jelmer Vernooij
Run autopep8.
2179
                                  }, [b'f', b'g'],
6963.2.3 by Jelmer Vernooij
Fix some more tests.
2180
                                 [(b'f', b'a'), (b'f', b'b'),
2181
                                  (b'g', b'b'), (b'g', b'a')])
2182
2183
        self.assertSplitByPrefix({b'f': [(b'f', b'a'), (b'f', b'b')],
2184
                                  b'g': [(b'g', b'b'), (b'g', b'a')],
7143.15.2 by Jelmer Vernooij
Run autopep8.
2185
                                  }, [b'f', b'g'],
6963.2.3 by Jelmer Vernooij
Fix some more tests.
2186
                                 [(b'f', b'a'), (b'f', b'b'),
2187
                                  (b'g', b'b'), (b'g', b'a')])
2188
2189
        self.assertSplitByPrefix({b'f': [(b'f', b'a'), (b'f', b'b')],
2190
                                  b'g': [(b'g', b'b'), (b'g', b'a')],
2191
                                  b'': [(b'a',), (b'b',)]
7143.15.2 by Jelmer Vernooij
Run autopep8.
2192
                                  }, [b'f', b'g', b''],
6963.2.3 by Jelmer Vernooij
Fix some more tests.
2193
                                 [(b'f', b'a'), (b'g', b'b'),
2194
                                  (b'a',), (b'b',),
2195
                                  (b'g', b'a'), (b'f', b'b')])
4039.3.6 by John Arbash Meinel
Turn _split_by_prefix into a classmethod, and add direct tests.
2196
2197
3350.8.1 by Robert Collins
KnitVersionedFiles.add_fallback_versioned_files exists.
2198
class TestStacking(KnitTests):
2199
2200
    def get_basis_and_test_knit(self):
2201
        basis = self.make_test_knit(name='basis')
3350.8.2 by Robert Collins
stacked get_parent_map.
2202
        basis = RecordingVersionedFilesDecorator(basis)
3350.8.1 by Robert Collins
KnitVersionedFiles.add_fallback_versioned_files exists.
2203
        test = self.make_test_knit(name='test')
2204
        test.add_fallback_versioned_files(basis)
2205
        return basis, test
2206
2207
    def test_add_fallback_versioned_files(self):
2208
        basis = self.make_test_knit(name='basis')
2209
        test = self.make_test_knit(name='test')
2210
        # It must not error; other tests test that the fallback is referred to
2211
        # when accessing data.
2212
        test.add_fallback_versioned_files(basis)
2213
2214
    def test_add_lines(self):
3350.8.9 by Robert Collins
define behaviour for add_lines with stacked storage.
2215
        # lines added to the test are not added to the basis
2216
        basis, test = self.get_basis_and_test_knit()
6985 by Jelmer Vernooij
Merge lp:~jelmer/brz/python3-weave-fmt.
2217
        key = (b'foo',)
2218
        key_basis = (b'bar',)
2219
        key_cross_border = (b'quux',)
2220
        key_delta = (b'zaphod',)
2221
        test.add_lines(key, (), [b'foo\n'])
3350.8.9 by Robert Collins
define behaviour for add_lines with stacked storage.
2222
        self.assertEqual({}, basis.get_parent_map([key]))
2223
        # lines added to the test that reference across the stack do a
2224
        # fulltext.
6985 by Jelmer Vernooij
Merge lp:~jelmer/brz/python3-weave-fmt.
2225
        basis.add_lines(key_basis, (), [b'foo\n'])
3350.8.9 by Robert Collins
define behaviour for add_lines with stacked storage.
2226
        basis.calls = []
6985 by Jelmer Vernooij
Merge lp:~jelmer/brz/python3-weave-fmt.
2227
        test.add_lines(key_cross_border, (key_basis,), [b'foo\n'])
3350.8.9 by Robert Collins
define behaviour for add_lines with stacked storage.
2228
        self.assertEqual('fulltext', test._index.get_method(key_cross_border))
3830.3.10 by Martin Pool
Update more stacking effort tests
2229
        # we don't even need to look at the basis to see that this should be
2230
        # stored as a fulltext
2231
        self.assertEqual([], basis.calls)
3350.8.9 by Robert Collins
define behaviour for add_lines with stacked storage.
2232
        # Subsequent adds do delta.
3350.8.14 by Robert Collins
Review feedback.
2233
        basis.calls = []
6985 by Jelmer Vernooij
Merge lp:~jelmer/brz/python3-weave-fmt.
2234
        test.add_lines(key_delta, (key_cross_border,), [b'foo\n'])
3350.8.9 by Robert Collins
define behaviour for add_lines with stacked storage.
2235
        self.assertEqual('line-delta', test._index.get_method(key_delta))
2236
        self.assertEqual([], basis.calls)
3350.8.1 by Robert Collins
KnitVersionedFiles.add_fallback_versioned_files exists.
2237
2238
    def test_annotate(self):
3350.8.8 by Robert Collins
Stacking and knits don't play nice for annotation yet.
2239
        # annotations from the test knit are answered without asking the basis
2240
        basis, test = self.get_basis_and_test_knit()
6985 by Jelmer Vernooij
Merge lp:~jelmer/brz/python3-weave-fmt.
2241
        key = (b'foo',)
2242
        key_basis = (b'bar',)
2243
        test.add_lines(key, (), [b'foo\n'])
3350.8.8 by Robert Collins
Stacking and knits don't play nice for annotation yet.
2244
        details = test.annotate(key)
6985 by Jelmer Vernooij
Merge lp:~jelmer/brz/python3-weave-fmt.
2245
        self.assertEqual([(key, b'foo\n')], details)
3350.8.8 by Robert Collins
Stacking and knits don't play nice for annotation yet.
2246
        self.assertEqual([], basis.calls)
2247
        # But texts that are not in the test knit are looked for in the basis
2248
        # directly.
6985 by Jelmer Vernooij
Merge lp:~jelmer/brz/python3-weave-fmt.
2249
        basis.add_lines(key_basis, (), [b'foo\n', b'bar\n'])
3350.8.8 by Robert Collins
Stacking and knits don't play nice for annotation yet.
2250
        basis.calls = []
2251
        details = test.annotate(key_basis)
7143.15.2 by Jelmer Vernooij
Run autopep8.
2252
        self.assertEqual(
2253
            [(key_basis, b'foo\n'), (key_basis, b'bar\n')], details)
3350.9.1 by Robert Collins
Redo annotate more simply, using just the public interfaces for VersionedFiles.
2254
        # Not optimised to date:
2255
        # self.assertEqual([("annotate", key_basis)], basis.calls)
6619.3.12 by Jelmer Vernooij
Use 2to3 set_literal fixer.
2256
        self.assertEqual([('get_parent_map', {key_basis}),
7143.15.2 by Jelmer Vernooij
Run autopep8.
2257
                          ('get_parent_map', {key_basis}),
2258
                          ('get_record_stream', [key_basis], 'topological', True)],
2259
                         basis.calls)
3350.8.1 by Robert Collins
KnitVersionedFiles.add_fallback_versioned_files exists.
2260
2261
    def test_check(self):
3517.4.19 by Martin Pool
Update test for knit.check() to expect it to recurse into fallback vfs
2262
        # At the moment checking a stacked knit does implicitly check the
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
2263
        # fallback files.
3350.8.1 by Robert Collins
KnitVersionedFiles.add_fallback_versioned_files exists.
2264
        basis, test = self.get_basis_and_test_knit()
2265
        test.check()
2266
2267
    def test_get_parent_map(self):
3350.8.2 by Robert Collins
stacked get_parent_map.
2268
        # parents in the test knit are answered without asking the basis
2269
        basis, test = self.get_basis_and_test_knit()
6985 by Jelmer Vernooij
Merge lp:~jelmer/brz/python3-weave-fmt.
2270
        key = (b'foo',)
2271
        key_basis = (b'bar',)
2272
        key_missing = (b'missing',)
3350.8.2 by Robert Collins
stacked get_parent_map.
2273
        test.add_lines(key, (), [])
2274
        parent_map = test.get_parent_map([key])
2275
        self.assertEqual({key: ()}, parent_map)
2276
        self.assertEqual([], basis.calls)
2277
        # But parents that are not in the test knit are looked for in the basis
2278
        basis.add_lines(key_basis, (), [])
2279
        basis.calls = []
2280
        parent_map = test.get_parent_map([key, key_basis, key_missing])
2281
        self.assertEqual({key: (),
7143.15.2 by Jelmer Vernooij
Run autopep8.
2282
                          key_basis: ()}, parent_map)
6619.3.12 by Jelmer Vernooij
Use 2to3 set_literal fixer.
2283
        self.assertEqual([("get_parent_map", {key_basis, key_missing})],
7143.15.2 by Jelmer Vernooij
Run autopep8.
2284
                         basis.calls)
3350.8.1 by Robert Collins
KnitVersionedFiles.add_fallback_versioned_files exists.
2285
3350.8.7 by Robert Collins
get_record_stream for fulltexts working (but note extreme memory use!).
2286
    def test_get_record_stream_unordered_fulltexts(self):
2287
        # records from the test knit are answered without asking the basis:
2288
        basis, test = self.get_basis_and_test_knit()
6985 by Jelmer Vernooij
Merge lp:~jelmer/brz/python3-weave-fmt.
2289
        key = (b'foo',)
2290
        key_basis = (b'bar',)
2291
        key_missing = (b'missing',)
2292
        test.add_lines(key, (), [b'foo\n'])
3350.8.7 by Robert Collins
get_record_stream for fulltexts working (but note extreme memory use!).
2293
        records = list(test.get_record_stream([key], 'unordered', True))
2294
        self.assertEqual(1, len(records))
2295
        self.assertEqual([], basis.calls)
2296
        # Missing (from test knit) objects are retrieved from the basis:
6985 by Jelmer Vernooij
Merge lp:~jelmer/brz/python3-weave-fmt.
2297
        basis.add_lines(key_basis, (), [b'foo\n', b'bar\n'])
3350.8.7 by Robert Collins
get_record_stream for fulltexts working (but note extreme memory use!).
2298
        basis.calls = []
2299
        records = list(test.get_record_stream([key_basis, key_missing],
7143.15.2 by Jelmer Vernooij
Run autopep8.
2300
                                              'unordered', True))
3350.8.7 by Robert Collins
get_record_stream for fulltexts working (but note extreme memory use!).
2301
        self.assertEqual(2, len(records))
2302
        calls = list(basis.calls)
2303
        for record in records:
2304
            self.assertSubset([record.key], (key_basis, key_missing))
2305
            if record.key == key_missing:
2306
                self.assertIsInstance(record, AbsentContentFactory)
2307
            else:
2308
                reference = list(basis.get_record_stream([key_basis],
7143.15.2 by Jelmer Vernooij
Run autopep8.
2309
                                                         'unordered', True))[0]
3350.8.7 by Robert Collins
get_record_stream for fulltexts working (but note extreme memory use!).
2310
                self.assertEqual(reference.key, record.key)
2311
                self.assertEqual(reference.sha1, record.sha1)
2312
                self.assertEqual(reference.storage_kind, record.storage_kind)
2313
                self.assertEqual(reference.get_bytes_as(reference.storage_kind),
7143.15.2 by Jelmer Vernooij
Run autopep8.
2314
                                 record.get_bytes_as(record.storage_kind))
3350.8.7 by Robert Collins
get_record_stream for fulltexts working (but note extreme memory use!).
2315
                self.assertEqual(reference.get_bytes_as('fulltext'),
7143.15.2 by Jelmer Vernooij
Run autopep8.
2316
                                 record.get_bytes_as('fulltext'))
3350.8.14 by Robert Collins
Review feedback.
2317
        # It's not strictly minimal, but it seems reasonable for now for it to
3350.8.7 by Robert Collins
get_record_stream for fulltexts working (but note extreme memory use!).
2318
        # ask which fallbacks have which parents.
2319
        self.assertEqual([
6619.3.12 by Jelmer Vernooij
Use 2to3 set_literal fixer.
2320
            ("get_parent_map", {key_basis, key_missing}),
3350.8.7 by Robert Collins
get_record_stream for fulltexts working (but note extreme memory use!).
2321
            ("get_record_stream", [key_basis], 'unordered', True)],
2322
            calls)
2323
2324
    def test_get_record_stream_ordered_fulltexts(self):
2325
        # ordering is preserved down into the fallback store.
2326
        basis, test = self.get_basis_and_test_knit()
6985 by Jelmer Vernooij
Merge lp:~jelmer/brz/python3-weave-fmt.
2327
        key = (b'foo',)
2328
        key_basis = (b'bar',)
2329
        key_basis_2 = (b'quux',)
2330
        key_missing = (b'missing',)
2331
        test.add_lines(key, (key_basis,), [b'foo\n'])
3350.8.7 by Robert Collins
get_record_stream for fulltexts working (but note extreme memory use!).
2332
        # Missing (from test knit) objects are retrieved from the basis:
6985 by Jelmer Vernooij
Merge lp:~jelmer/brz/python3-weave-fmt.
2333
        basis.add_lines(key_basis, (key_basis_2,), [b'foo\n', b'bar\n'])
2334
        basis.add_lines(key_basis_2, (), [b'quux\n'])
3350.8.7 by Robert Collins
get_record_stream for fulltexts working (but note extreme memory use!).
2335
        basis.calls = []
2336
        # ask for in non-topological order
2337
        records = list(test.get_record_stream(
2338
            [key, key_basis, key_missing, key_basis_2], 'topological', True))
2339
        self.assertEqual(4, len(records))
2340
        results = []
2341
        for record in records:
2342
            self.assertSubset([record.key],
7143.15.2 by Jelmer Vernooij
Run autopep8.
2343
                              (key_basis, key_missing, key_basis_2, key))
3350.8.7 by Robert Collins
get_record_stream for fulltexts working (but note extreme memory use!).
2344
            if record.key == key_missing:
2345
                self.assertIsInstance(record, AbsentContentFactory)
2346
            else:
2347
                results.append((record.key, record.sha1, record.storage_kind,
7143.15.2 by Jelmer Vernooij
Run autopep8.
2348
                                record.get_bytes_as('fulltext')))
3350.8.7 by Robert Collins
get_record_stream for fulltexts working (but note extreme memory use!).
2349
        calls = list(basis.calls)
2350
        order = [record[0] for record in results]
2351
        self.assertEqual([key_basis_2, key_basis, key], order)
2352
        for result in results:
2353
            if result[0] == key:
2354
                source = test
2355
            else:
2356
                source = basis
6634.2.1 by Martin
Apply 2to3 next fixer and make compatible
2357
            record = next(source.get_record_stream([result[0]], 'unordered',
7143.15.2 by Jelmer Vernooij
Run autopep8.
2358
                                                   True))
3350.8.7 by Robert Collins
get_record_stream for fulltexts working (but note extreme memory use!).
2359
            self.assertEqual(record.key, result[0])
2360
            self.assertEqual(record.sha1, result[1])
4005.3.6 by Robert Collins
Support delta_closure=True with NetworkRecordStream to transmit deltas over the wire when full text extraction is required on the far end.
2361
            # We used to check that the storage kind matched, but actually it
2362
            # depends on whether it was sourced from the basis, or in a single
2363
            # group, because asking for full texts returns proxy objects to a
2364
            # _ContentMapGenerator object; so checking the kind is unneeded.
3350.8.7 by Robert Collins
get_record_stream for fulltexts working (but note extreme memory use!).
2365
            self.assertEqual(record.get_bytes_as('fulltext'), result[3])
3350.8.14 by Robert Collins
Review feedback.
2366
        # It's not strictly minimal, but it seems reasonable for now for it to
3350.8.7 by Robert Collins
get_record_stream for fulltexts working (but note extreme memory use!).
2367
        # ask which fallbacks have which parents.
6973.7.8 by Jelmer Vernooij
Fix more tests.
2368
        self.assertEqual(2, len(calls))
2369
        self.assertEqual(
7143.15.2 by Jelmer Vernooij
Run autopep8.
2370
            ("get_parent_map", {key_basis, key_basis_2, key_missing}),
2371
            calls[0])
6997 by Jelmer Vernooij
Merge lp:~jelmer/brz/python3-f
2372
        # topological is requested from the fallback, because that is what
2373
        # was requested at the top level.
2374
        self.assertIn(
7143.15.2 by Jelmer Vernooij
Run autopep8.
2375
            calls[1], [
2376
                ("get_record_stream", [key_basis_2,
2377
                                       key_basis], 'topological', True),
6997 by Jelmer Vernooij
Merge lp:~jelmer/brz/python3-f
2378
                ("get_record_stream", [key_basis, key_basis_2], 'topological', True)])
3350.8.7 by Robert Collins
get_record_stream for fulltexts working (but note extreme memory use!).
2379
3350.8.6 by Robert Collins
get_record_stream stacking for delta access.
2380
    def test_get_record_stream_unordered_deltas(self):
2381
        # records from the test knit are answered without asking the basis:
2382
        basis, test = self.get_basis_and_test_knit()
6985 by Jelmer Vernooij
Merge lp:~jelmer/brz/python3-weave-fmt.
2383
        key = (b'foo',)
2384
        key_basis = (b'bar',)
2385
        key_missing = (b'missing',)
2386
        test.add_lines(key, (), [b'foo\n'])
3350.8.6 by Robert Collins
get_record_stream stacking for delta access.
2387
        records = list(test.get_record_stream([key], 'unordered', False))
2388
        self.assertEqual(1, len(records))
2389
        self.assertEqual([], basis.calls)
2390
        # Missing (from test knit) objects are retrieved from the basis:
6985 by Jelmer Vernooij
Merge lp:~jelmer/brz/python3-weave-fmt.
2391
        basis.add_lines(key_basis, (), [b'foo\n', b'bar\n'])
3350.8.6 by Robert Collins
get_record_stream stacking for delta access.
2392
        basis.calls = []
2393
        records = list(test.get_record_stream([key_basis, key_missing],
7143.15.2 by Jelmer Vernooij
Run autopep8.
2394
                                              'unordered', False))
3350.8.6 by Robert Collins
get_record_stream stacking for delta access.
2395
        self.assertEqual(2, len(records))
2396
        calls = list(basis.calls)
2397
        for record in records:
2398
            self.assertSubset([record.key], (key_basis, key_missing))
2399
            if record.key == key_missing:
2400
                self.assertIsInstance(record, AbsentContentFactory)
2401
            else:
2402
                reference = list(basis.get_record_stream([key_basis],
7143.15.2 by Jelmer Vernooij
Run autopep8.
2403
                                                         'unordered', False))[0]
3350.8.6 by Robert Collins
get_record_stream stacking for delta access.
2404
                self.assertEqual(reference.key, record.key)
2405
                self.assertEqual(reference.sha1, record.sha1)
2406
                self.assertEqual(reference.storage_kind, record.storage_kind)
2407
                self.assertEqual(reference.get_bytes_as(reference.storage_kind),
7143.15.2 by Jelmer Vernooij
Run autopep8.
2408
                                 record.get_bytes_as(record.storage_kind))
3350.8.14 by Robert Collins
Review feedback.
2409
        # It's not strictly minimal, but it seems reasonable for now for it to
3350.8.6 by Robert Collins
get_record_stream stacking for delta access.
2410
        # ask which fallbacks have which parents.
2411
        self.assertEqual([
6619.3.12 by Jelmer Vernooij
Use 2to3 set_literal fixer.
2412
            ("get_parent_map", {key_basis, key_missing}),
3350.8.6 by Robert Collins
get_record_stream stacking for delta access.
2413
            ("get_record_stream", [key_basis], 'unordered', False)],
2414
            calls)
2415
2416
    def test_get_record_stream_ordered_deltas(self):
2417
        # ordering is preserved down into the fallback store.
2418
        basis, test = self.get_basis_and_test_knit()
6985 by Jelmer Vernooij
Merge lp:~jelmer/brz/python3-weave-fmt.
2419
        key = (b'foo',)
2420
        key_basis = (b'bar',)
2421
        key_basis_2 = (b'quux',)
2422
        key_missing = (b'missing',)
2423
        test.add_lines(key, (key_basis,), [b'foo\n'])
3350.8.6 by Robert Collins
get_record_stream stacking for delta access.
2424
        # Missing (from test knit) objects are retrieved from the basis:
6985 by Jelmer Vernooij
Merge lp:~jelmer/brz/python3-weave-fmt.
2425
        basis.add_lines(key_basis, (key_basis_2,), [b'foo\n', b'bar\n'])
2426
        basis.add_lines(key_basis_2, (), [b'quux\n'])
3350.8.6 by Robert Collins
get_record_stream stacking for delta access.
2427
        basis.calls = []
2428
        # ask for in non-topological order
2429
        records = list(test.get_record_stream(
2430
            [key, key_basis, key_missing, key_basis_2], 'topological', False))
2431
        self.assertEqual(4, len(records))
2432
        results = []
2433
        for record in records:
2434
            self.assertSubset([record.key],
7143.15.2 by Jelmer Vernooij
Run autopep8.
2435
                              (key_basis, key_missing, key_basis_2, key))
3350.8.6 by Robert Collins
get_record_stream stacking for delta access.
2436
            if record.key == key_missing:
2437
                self.assertIsInstance(record, AbsentContentFactory)
2438
            else:
2439
                results.append((record.key, record.sha1, record.storage_kind,
7143.15.2 by Jelmer Vernooij
Run autopep8.
2440
                                record.get_bytes_as(record.storage_kind)))
3350.8.6 by Robert Collins
get_record_stream stacking for delta access.
2441
        calls = list(basis.calls)
2442
        order = [record[0] for record in results]
2443
        self.assertEqual([key_basis_2, key_basis, key], order)
2444
        for result in results:
2445
            if result[0] == key:
2446
                source = test
2447
            else:
2448
                source = basis
6634.2.1 by Martin
Apply 2to3 next fixer and make compatible
2449
            record = next(source.get_record_stream([result[0]], 'unordered',
7143.15.2 by Jelmer Vernooij
Run autopep8.
2450
                                                   False))
3350.8.6 by Robert Collins
get_record_stream stacking for delta access.
2451
            self.assertEqual(record.key, result[0])
2452
            self.assertEqual(record.sha1, result[1])
2453
            self.assertEqual(record.storage_kind, result[2])
7143.15.2 by Jelmer Vernooij
Run autopep8.
2454
            self.assertEqual(record.get_bytes_as(
2455
                record.storage_kind), result[3])
3350.8.14 by Robert Collins
Review feedback.
2456
        # It's not strictly minimal, but it seems reasonable for now for it to
3350.8.6 by Robert Collins
get_record_stream stacking for delta access.
2457
        # ask which fallbacks have which parents.
2458
        self.assertEqual([
6619.3.12 by Jelmer Vernooij
Use 2to3 set_literal fixer.
2459
            ("get_parent_map", {key_basis, key_basis_2, key_missing}),
3350.8.6 by Robert Collins
get_record_stream stacking for delta access.
2460
            ("get_record_stream", [key_basis_2, key_basis], 'topological', False)],
2461
            calls)
3350.8.1 by Robert Collins
KnitVersionedFiles.add_fallback_versioned_files exists.
2462
2463
    def test_get_sha1s(self):
3350.8.3 by Robert Collins
VF.get_sha1s needed changing to be stackable.
2464
        # sha1's in the test knit are answered without asking the basis
2465
        basis, test = self.get_basis_and_test_knit()
6973.14.2 by Jelmer Vernooij
Fix some knit tests.
2466
        key = (b'foo',)
2467
        key_basis = (b'bar',)
2468
        key_missing = (b'missing',)
2469
        test.add_lines(key, (), [b'foo\n'])
2470
        key_sha1sum = osutils.sha_string(b'foo\n')
3350.8.3 by Robert Collins
VF.get_sha1s needed changing to be stackable.
2471
        sha1s = test.get_sha1s([key])
2472
        self.assertEqual({key: key_sha1sum}, sha1s)
2473
        self.assertEqual([], basis.calls)
2474
        # But texts that are not in the test knit are looked for in the basis
2475
        # directly (rather than via text reconstruction) so that remote servers
2476
        # etc don't have to answer with full content.
6973.14.2 by Jelmer Vernooij
Fix some knit tests.
2477
        basis.add_lines(key_basis, (), [b'foo\n', b'bar\n'])
2478
        basis_sha1sum = osutils.sha_string(b'foo\nbar\n')
3350.8.3 by Robert Collins
VF.get_sha1s needed changing to be stackable.
2479
        basis.calls = []
2480
        sha1s = test.get_sha1s([key, key_missing, key_basis])
2481
        self.assertEqual({key: key_sha1sum,
7143.15.2 by Jelmer Vernooij
Run autopep8.
2482
                          key_basis: basis_sha1sum}, sha1s)
6619.3.12 by Jelmer Vernooij
Use 2to3 set_literal fixer.
2483
        self.assertEqual([("get_sha1s", {key_basis, key_missing})],
7143.15.2 by Jelmer Vernooij
Run autopep8.
2484
                         basis.calls)
3350.8.1 by Robert Collins
KnitVersionedFiles.add_fallback_versioned_files exists.
2485
2486
    def test_insert_record_stream(self):
3350.8.10 by Robert Collins
Stacked insert_record_stream.
2487
        # records are inserted as normal; insert_record_stream builds on
3350.8.14 by Robert Collins
Review feedback.
2488
        # add_lines, so a smoke test should be all that's needed:
6973.14.2 by Jelmer Vernooij
Fix some knit tests.
2489
        key_basis = (b'bar',)
2490
        key_delta = (b'zaphod',)
3350.8.10 by Robert Collins
Stacked insert_record_stream.
2491
        basis, test = self.get_basis_and_test_knit()
2492
        source = self.make_test_knit(name='source')
6973.14.2 by Jelmer Vernooij
Fix some knit tests.
2493
        basis.add_lines(key_basis, (), [b'foo\n'])
3350.8.10 by Robert Collins
Stacked insert_record_stream.
2494
        basis.calls = []
6973.14.2 by Jelmer Vernooij
Fix some knit tests.
2495
        source.add_lines(key_basis, (), [b'foo\n'])
2496
        source.add_lines(key_delta, (key_basis,), [b'bar\n'])
3350.8.10 by Robert Collins
Stacked insert_record_stream.
2497
        stream = source.get_record_stream([key_delta], 'unordered', False)
2498
        test.insert_record_stream(stream)
3830.3.9 by Martin Pool
Simplify kvf insert_record_stream; add has_key shorthand methods; update stacking effort tests
2499
        # XXX: this does somewhat too many calls in making sure of whether it
2500
        # has to recreate the full text.
6619.3.12 by Jelmer Vernooij
Use 2to3 set_literal fixer.
2501
        self.assertEqual([("get_parent_map", {key_basis}),
7143.15.2 by Jelmer Vernooij
Run autopep8.
2502
                          ('get_parent_map', {key_basis}),
2503
                          ('get_record_stream', [key_basis], 'unordered', True)],
2504
                         basis.calls)
2505
        self.assertEqual({key_delta: (key_basis,)},
2506
                         test.get_parent_map([key_delta]))
6973.14.2 by Jelmer Vernooij
Fix some knit tests.
2507
        self.assertEqual(b'bar\n', next(test.get_record_stream([key_delta],
7143.15.2 by Jelmer Vernooij
Run autopep8.
2508
                                                               'unordered', True)).get_bytes_as('fulltext'))
3350.8.1 by Robert Collins
KnitVersionedFiles.add_fallback_versioned_files exists.
2509
2510
    def test_iter_lines_added_or_present_in_keys(self):
3350.8.5 by Robert Collins
Iter_lines_added_or_present_in_keys stacks.
2511
        # Lines from the basis are returned, and lines for a given key are only
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
2512
        # returned once.
6985 by Jelmer Vernooij
Merge lp:~jelmer/brz/python3-weave-fmt.
2513
        key1 = (b'foo1',)
2514
        key2 = (b'foo2',)
3350.8.5 by Robert Collins
Iter_lines_added_or_present_in_keys stacks.
2515
        # all sources are asked for keys:
2516
        basis, test = self.get_basis_and_test_knit()
6985 by Jelmer Vernooij
Merge lp:~jelmer/brz/python3-weave-fmt.
2517
        basis.add_lines(key1, (), [b"foo"])
3350.8.5 by Robert Collins
Iter_lines_added_or_present_in_keys stacks.
2518
        basis.calls = []
2519
        lines = list(test.iter_lines_added_or_present_in_keys([key1]))
6985 by Jelmer Vernooij
Merge lp:~jelmer/brz/python3-weave-fmt.
2520
        self.assertEqual([(b"foo\n", key1)], lines)
6619.3.12 by Jelmer Vernooij
Use 2to3 set_literal fixer.
2521
        self.assertEqual([("iter_lines_added_or_present_in_keys", {key1})],
7143.15.2 by Jelmer Vernooij
Run autopep8.
2522
                         basis.calls)
3350.8.5 by Robert Collins
Iter_lines_added_or_present_in_keys stacks.
2523
        # keys in both are not duplicated:
6985 by Jelmer Vernooij
Merge lp:~jelmer/brz/python3-weave-fmt.
2524
        test.add_lines(key2, (), [b"bar\n"])
2525
        basis.add_lines(key2, (), [b"bar\n"])
3350.8.5 by Robert Collins
Iter_lines_added_or_present_in_keys stacks.
2526
        basis.calls = []
2527
        lines = list(test.iter_lines_added_or_present_in_keys([key2]))
6985 by Jelmer Vernooij
Merge lp:~jelmer/brz/python3-weave-fmt.
2528
        self.assertEqual([(b"bar\n", key2)], lines)
3350.8.5 by Robert Collins
Iter_lines_added_or_present_in_keys stacks.
2529
        self.assertEqual([], basis.calls)
3350.8.1 by Robert Collins
KnitVersionedFiles.add_fallback_versioned_files exists.
2530
2531
    def test_keys(self):
6985 by Jelmer Vernooij
Merge lp:~jelmer/brz/python3-weave-fmt.
2532
        key1 = (b'foo1',)
2533
        key2 = (b'foo2',)
3350.8.4 by Robert Collins
Vf.keys() stacking support.
2534
        # all sources are asked for keys:
2535
        basis, test = self.get_basis_and_test_knit()
2536
        keys = test.keys()
2537
        self.assertEqual(set(), set(keys))
2538
        self.assertEqual([("keys",)], basis.calls)
2539
        # keys from a basis are returned:
2540
        basis.add_lines(key1, (), [])
2541
        basis.calls = []
2542
        keys = test.keys()
6619.3.12 by Jelmer Vernooij
Use 2to3 set_literal fixer.
2543
        self.assertEqual({key1}, set(keys))
3350.8.4 by Robert Collins
Vf.keys() stacking support.
2544
        self.assertEqual([("keys",)], basis.calls)
2545
        # keys in both are not duplicated:
2546
        test.add_lines(key2, (), [])
2547
        basis.add_lines(key2, (), [])
2548
        basis.calls = []
2549
        keys = test.keys()
2550
        self.assertEqual(2, len(keys))
6619.3.12 by Jelmer Vernooij
Use 2to3 set_literal fixer.
2551
        self.assertEqual({key1, key2}, set(keys))
3350.8.4 by Robert Collins
Vf.keys() stacking support.
2552
        self.assertEqual([("keys",)], basis.calls)
3350.8.1 by Robert Collins
KnitVersionedFiles.add_fallback_versioned_files exists.
2553
2554
    def test_add_mpdiffs(self):
3350.8.11 by Robert Collins
Stacked add_mpdiffs.
2555
        # records are inserted as normal; add_mpdiff builds on
3350.8.14 by Robert Collins
Review feedback.
2556
        # add_lines, so a smoke test should be all that's needed:
6985 by Jelmer Vernooij
Merge lp:~jelmer/brz/python3-weave-fmt.
2557
        key_basis = (b'bar',)
2558
        key_delta = (b'zaphod',)
3350.8.11 by Robert Collins
Stacked add_mpdiffs.
2559
        basis, test = self.get_basis_and_test_knit()
2560
        source = self.make_test_knit(name='source')
6985 by Jelmer Vernooij
Merge lp:~jelmer/brz/python3-weave-fmt.
2561
        basis.add_lines(key_basis, (), [b'foo\n'])
3350.8.11 by Robert Collins
Stacked add_mpdiffs.
2562
        basis.calls = []
6985 by Jelmer Vernooij
Merge lp:~jelmer/brz/python3-weave-fmt.
2563
        source.add_lines(key_basis, (), [b'foo\n'])
2564
        source.add_lines(key_delta, (key_basis,), [b'bar\n'])
3350.8.11 by Robert Collins
Stacked add_mpdiffs.
2565
        diffs = source.make_mpdiffs([key_delta])
2566
        test.add_mpdiffs([(key_delta, (key_basis,),
7143.15.2 by Jelmer Vernooij
Run autopep8.
2567
                           source.get_sha1s([key_delta])[key_delta], diffs[0])])
6619.3.12 by Jelmer Vernooij
Use 2to3 set_literal fixer.
2568
        self.assertEqual([("get_parent_map", {key_basis}),
7143.15.2 by Jelmer Vernooij
Run autopep8.
2569
                          ('get_record_stream', [key_basis], 'unordered', True), ],
2570
                         basis.calls)
2571
        self.assertEqual({key_delta: (key_basis,)},
2572
                         test.get_parent_map([key_delta]))
6973.14.2 by Jelmer Vernooij
Fix some knit tests.
2573
        self.assertEqual(b'bar\n', next(test.get_record_stream([key_delta],
7143.15.2 by Jelmer Vernooij
Run autopep8.
2574
                                                               'unordered', True)).get_bytes_as('fulltext'))
3350.8.1 by Robert Collins
KnitVersionedFiles.add_fallback_versioned_files exists.
2575
2576
    def test_make_mpdiffs(self):
3350.8.12 by Robert Collins
Stacked make_mpdiffs.
2577
        # Generating an mpdiff across a stacking boundary should detect parent
2578
        # texts regions.
6985 by Jelmer Vernooij
Merge lp:~jelmer/brz/python3-weave-fmt.
2579
        key = (b'foo',)
2580
        key_left = (b'bar',)
2581
        key_right = (b'zaphod',)
3350.8.12 by Robert Collins
Stacked make_mpdiffs.
2582
        basis, test = self.get_basis_and_test_knit()
6985 by Jelmer Vernooij
Merge lp:~jelmer/brz/python3-weave-fmt.
2583
        basis.add_lines(key_left, (), [b'bar\n'])
2584
        basis.add_lines(key_right, (), [b'zaphod\n'])
3350.8.12 by Robert Collins
Stacked make_mpdiffs.
2585
        basis.calls = []
2586
        test.add_lines(key, (key_left, key_right),
7143.15.2 by Jelmer Vernooij
Run autopep8.
2587
                       [b'bar\n', b'foo\n', b'zaphod\n'])
3350.8.12 by Robert Collins
Stacked make_mpdiffs.
2588
        diffs = test.make_mpdiffs([key])
2589
        self.assertEqual([
2590
            multiparent.MultiParent([multiparent.ParentText(0, 0, 0, 1),
7143.15.2 by Jelmer Vernooij
Run autopep8.
2591
                                     multiparent.NewText([b'foo\n']),
2592
                                     multiparent.ParentText(1, 0, 2, 1)])],
2593
                         diffs)
3830.3.10 by Martin Pool
Update more stacking effort tests
2594
        self.assertEqual(3, len(basis.calls))
3350.8.12 by Robert Collins
Stacked make_mpdiffs.
2595
        self.assertEqual([
6619.3.12 by Jelmer Vernooij
Use 2to3 set_literal fixer.
2596
            ("get_parent_map", {key_left, key_right}),
2597
            ("get_parent_map", {key_left, key_right}),
3350.8.12 by Robert Collins
Stacked make_mpdiffs.
2598
            ],
3830.3.10 by Martin Pool
Update more stacking effort tests
2599
            basis.calls[:-1])
2600
        last_call = basis.calls[-1]
3350.8.14 by Robert Collins
Review feedback.
2601
        self.assertEqual('get_record_stream', last_call[0])
6619.3.12 by Jelmer Vernooij
Use 2to3 set_literal fixer.
2602
        self.assertEqual({key_left, key_right}, set(last_call[1]))
4537.3.5 by John Arbash Meinel
Fix 3 tests that assumed it would use 'unordered' in the fallback,
2603
        self.assertEqual('topological', last_call[2])
3350.8.14 by Robert Collins
Review feedback.
2604
        self.assertEqual(True, last_call[3])
4005.3.6 by Robert Collins
Support delta_closure=True with NetworkRecordStream to transmit deltas over the wire when full text extraction is required on the far end.
2605
2606
2607
class TestNetworkBehaviour(KnitTests):
2608
    """Tests for getting data out of/into knits over the network."""
2609
2610
    def test_include_delta_closure_generates_a_knit_delta_closure(self):
2611
        vf = self.make_test_knit(name='test')
2612
        # put in three texts, giving ft, delta, delta
6973.14.2 by Jelmer Vernooij
Fix some knit tests.
2613
        vf.add_lines((b'base',), (), [b'base\n', b'content\n'])
2614
        vf.add_lines((b'd1',), ((b'base',),), [b'd1\n'])
2615
        vf.add_lines((b'd2',), ((b'd1',),), [b'd2\n'])
4005.3.6 by Robert Collins
Support delta_closure=True with NetworkRecordStream to transmit deltas over the wire when full text extraction is required on the far end.
2616
        # But heuristics could interfere, so check what happened:
2617
        self.assertEqual(['knit-ft-gz', 'knit-delta-gz', 'knit-delta-gz'],
7143.15.2 by Jelmer Vernooij
Run autopep8.
2618
                         [record.storage_kind for record in
2619
                          vf.get_record_stream([(b'base',), (b'd1',), (b'd2',)],
2620
                                               'topological', False)])
4005.3.6 by Robert Collins
Support delta_closure=True with NetworkRecordStream to transmit deltas over the wire when full text extraction is required on the far end.
2621
        # generate a stream of just the deltas include_delta_closure=True,
2622
        # serialise to the network, and check that we get a delta closure on the wire.
7143.15.2 by Jelmer Vernooij
Run autopep8.
2623
        stream = vf.get_record_stream(
2624
            [(b'd1',), (b'd2',)], 'topological', True)
4005.3.6 by Robert Collins
Support delta_closure=True with NetworkRecordStream to transmit deltas over the wire when full text extraction is required on the far end.
2625
        netb = [record.get_bytes_as(record.storage_kind) for record in stream]
2626
        # The first bytes should be a memo from _ContentMapGenerator, and the
2627
        # second bytes should be empty (because its a API proxy not something
2628
        # for wire serialisation.
6973.14.2 by Jelmer Vernooij
Fix some knit tests.
2629
        self.assertEqual(b'', netb[1])
4005.3.6 by Robert Collins
Support delta_closure=True with NetworkRecordStream to transmit deltas over the wire when full text extraction is required on the far end.
2630
        bytes = netb[0]
2631
        kind, line_end = network_bytes_to_kind_and_offset(bytes)
2632
        self.assertEqual('knit-delta-closure', kind)
2633
2634
2635
class TestContentMapGenerator(KnitTests):
2636
    """Tests for ContentMapGenerator"""
2637
2638
    def test_get_record_stream_gives_records(self):
2639
        vf = self.make_test_knit(name='test')
2640
        # put in three texts, giving ft, delta, delta
6973.14.2 by Jelmer Vernooij
Fix some knit tests.
2641
        vf.add_lines((b'base',), (), [b'base\n', b'content\n'])
2642
        vf.add_lines((b'd1',), ((b'base',),), [b'd1\n'])
2643
        vf.add_lines((b'd2',), ((b'd1',),), [b'd2\n'])
2644
        keys = [(b'd1',), (b'd2',)]
4005.3.6 by Robert Collins
Support delta_closure=True with NetworkRecordStream to transmit deltas over the wire when full text extraction is required on the far end.
2645
        generator = _VFContentMapGenerator(vf, keys,
7143.15.2 by Jelmer Vernooij
Run autopep8.
2646
                                           global_map=vf.get_parent_map(keys))
4005.3.6 by Robert Collins
Support delta_closure=True with NetworkRecordStream to transmit deltas over the wire when full text extraction is required on the far end.
2647
        for record in generator.get_record_stream():
6973.14.2 by Jelmer Vernooij
Fix some knit tests.
2648
            if record.key == (b'd1',):
2649
                self.assertEqual(b'd1\n', record.get_bytes_as('fulltext'))
4005.3.6 by Robert Collins
Support delta_closure=True with NetworkRecordStream to transmit deltas over the wire when full text extraction is required on the far end.
2650
            else:
6973.14.2 by Jelmer Vernooij
Fix some knit tests.
2651
                self.assertEqual(b'd2\n', record.get_bytes_as('fulltext'))
4005.3.6 by Robert Collins
Support delta_closure=True with NetworkRecordStream to transmit deltas over the wire when full text extraction is required on the far end.
2652
2653
    def test_get_record_stream_kinds_are_raw(self):
2654
        vf = self.make_test_knit(name='test')
2655
        # put in three texts, giving ft, delta, delta
6973.14.2 by Jelmer Vernooij
Fix some knit tests.
2656
        vf.add_lines((b'base',), (), [b'base\n', b'content\n'])
2657
        vf.add_lines((b'd1',), ((b'base',),), [b'd1\n'])
2658
        vf.add_lines((b'd2',), ((b'd1',),), [b'd2\n'])
2659
        keys = [(b'base',), (b'd1',), (b'd2',)]
4005.3.6 by Robert Collins
Support delta_closure=True with NetworkRecordStream to transmit deltas over the wire when full text extraction is required on the far end.
2660
        generator = _VFContentMapGenerator(vf, keys,
7143.15.2 by Jelmer Vernooij
Run autopep8.
2661
                                           global_map=vf.get_parent_map(keys))
6973.14.2 by Jelmer Vernooij
Fix some knit tests.
2662
        kinds = {(b'base',): 'knit-delta-closure',
7143.15.2 by Jelmer Vernooij
Run autopep8.
2663
                 (b'd1',): 'knit-delta-closure-ref',
2664
                 (b'd2',): 'knit-delta-closure-ref',
2665
                 }
4005.3.6 by Robert Collins
Support delta_closure=True with NetworkRecordStream to transmit deltas over the wire when full text extraction is required on the far end.
2666
        for record in generator.get_record_stream():
2667
            self.assertEqual(kinds[record.key], record.storage_kind)