bzr branch
http://gegoxaren.bato24.eu/bzr/brz/remove-bazaar
| 
2484.1.12
by John Arbash Meinel
 Switch the layout to use a matching _knit_load_data_py.py and _knit_load_data_c.pyx  | 
1  | 
# Copyright (C) 2005, 2006, 2007 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
 | 
|
15  | 
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 | 
|
16  | 
||
17  | 
"""Tests for Knit data structure"""
 | 
|
18  | 
||
| 
2158.3.1
by Dmitry Vasiliev
 KnitIndex tests/fixes/optimizations  | 
19  | 
from cStringIO import StringIO  | 
| 
1563.2.4
by Robert Collins
 First cut at including the knit implementation of versioned_file.  | 
20  | 
import difflib  | 
| 
2329.1.1
by John Arbash Meinel
 Update _KnitData parser to raise more helpful errors when it detects corruption.  | 
21  | 
import gzip  | 
| 
2484.1.17
by John Arbash Meinel
 Workaround for Pyrex <0.9.5 and python >=2.5 incompatibilities.  | 
22  | 
import sys  | 
| 
1563.2.4
by Robert Collins
 First cut at including the knit implementation of versioned_file.  | 
23  | 
|
| 
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  | 
from bzrlib import (  | 
25  | 
errors,  | 
|
| 
2484.1.5
by John Arbash Meinel
 Simplistic implementations of custom parsers for options and parents  | 
26  | 
generate_ids,  | 
| 
2484.1.1
by John Arbash Meinel
 Add an initial function to read knit indexes in pyrex.  | 
27  | 
knit,  | 
| 
3350.8.12
by Robert Collins
 Stacked make_mpdiffs.  | 
28  | 
multiparent,  | 
| 
3734.2.4
by Vincent Ladeuil
 Fix python2.6 deprecation warnings related to hashlib.  | 
29  | 
osutils,  | 
| 
2592.3.66
by Robert Collins
 Allow adaption of KnitData to pack files.  | 
30  | 
pack,  | 
| 
2196.2.5
by John Arbash Meinel
 Add an exception class when the knit index storage method is unknown, and properly test for it  | 
31  | 
    )
 | 
| 
2158.3.1
by Dmitry Vasiliev
 KnitIndex tests/fixes/optimizations  | 
32  | 
from bzrlib.errors import (  | 
33  | 
RevisionAlreadyPresent,  | 
|
34  | 
KnitHeaderError,  | 
|
35  | 
RevisionNotPresent,  | 
|
36  | 
NoSuchFile,  | 
|
37  | 
    )
 | 
|
| 
2592.3.1
by Robert Collins
 Allow giving KnitVersionedFile an index object to use rather than implicitly creating one.  | 
38  | 
from bzrlib.index import *  | 
| 
1684.3.3
by Robert Collins
 Add a special cased weaves to knit converter.  | 
39  | 
from bzrlib.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.  | 
40  | 
AnnotatedKnitContent,  | 
| 
2151.1.1
by John Arbash Meinel
 (Dmitry Vasiliev) Tune KnitContent and add tests  | 
41  | 
KnitContent,  | 
| 
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.  | 
42  | 
KnitSequenceMatcher,  | 
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,  | 
| 
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.  | 
45  | 
_DirectPackAccess,  | 
46  | 
_KndxIndex,  | 
|
47  | 
_KnitGraphIndex,  | 
|
48  | 
_KnitKeyAccess,  | 
|
49  | 
make_file_factory,  | 
|
| 
2158.3.1
by Dmitry Vasiliev
 KnitIndex tests/fixes/optimizations  | 
50  | 
    )
 | 
| 
3789.2.10
by John Arbash Meinel
 The first function for KnitVersionedFiles can now retry on request.  | 
51  | 
from bzrlib.repofmt import pack_repo  | 
| 
2592.3.66
by Robert Collins
 Allow adaption of KnitData to pack files.  | 
52  | 
from bzrlib.tests import (  | 
53  | 
Feature,  | 
|
| 
3350.8.8
by Robert Collins
 Stacking and knits don't play nice for annotation yet.  | 
54  | 
KnownFailure,  | 
| 
2592.3.66
by Robert Collins
 Allow adaption of KnitData to pack files.  | 
55  | 
TestCase,  | 
56  | 
TestCaseWithMemoryTransport,  | 
|
57  | 
TestCaseWithTransport,  | 
|
| 
3787.1.1
by Robert Collins
 Embed the failed text in sha1 knit errors.  | 
58  | 
TestNotApplicable,  | 
| 
2592.3.66
by Robert Collins
 Allow adaption of KnitData to pack files.  | 
59  | 
    )
 | 
| 
2745.5.3
by Robert Collins
 * Move transport logging into a new transport class  | 
60  | 
from bzrlib.transport import get_transport  | 
| 
1563.2.13
by Robert Collins
 InterVersionedFile implemented.  | 
61  | 
from bzrlib.transport.memory import MemoryTransport  | 
| 
3052.2.3
by Robert Collins
 Handle insert_data_stream of an unannotated stream into an annotated knit.  | 
62  | 
from bzrlib.tuned_gzip import GzipFile  | 
| 
3350.8.2
by Robert Collins
 stacked get_parent_map.  | 
63  | 
from bzrlib.versionedfile import (  | 
| 
3350.8.6
by Robert Collins
 get_record_stream stacking for delta access.  | 
64  | 
AbsentContentFactory,  | 
| 
3350.8.2
by Robert Collins
 stacked get_parent_map.  | 
65  | 
ConstantMapper,  | 
66  | 
RecordingVersionedFilesDecorator,  | 
|
67  | 
    )
 | 
|
| 
1684.3.3
by Robert Collins
 Add a special cased weaves to knit converter.  | 
68  | 
|
69  | 
||
| 
2484.1.1
by John Arbash Meinel
 Add an initial function to read knit indexes in pyrex.  | 
70  | 
class _CompiledKnitFeature(Feature):  | 
71  | 
||
72  | 
def _probe(self):  | 
|
73  | 
try:  | 
|
| 
2484.1.12
by John Arbash Meinel
 Switch the layout to use a matching _knit_load_data_py.py and _knit_load_data_c.pyx  | 
74  | 
import bzrlib._knit_load_data_c  | 
| 
2484.1.1
by John Arbash Meinel
 Add an initial function to read knit indexes in pyrex.  | 
75  | 
except ImportError:  | 
76  | 
return False  | 
|
77  | 
return True  | 
|
78  | 
||
79  | 
def feature_name(self):  | 
|
| 
2484.1.12
by John Arbash Meinel
 Switch the layout to use a matching _knit_load_data_py.py and _knit_load_data_c.pyx  | 
80  | 
return 'bzrlib._knit_load_data_c'  | 
| 
2484.1.1
by John Arbash Meinel
 Add an initial function to read knit indexes in pyrex.  | 
81  | 
|
82  | 
CompiledKnitFeature = _CompiledKnitFeature()  | 
|
83  | 
||
84  | 
||
| 
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.  | 
85  | 
class KnitContentTestsMixin(object):  | 
| 
2151.1.1
by John Arbash Meinel
 (Dmitry Vasiliev) Tune KnitContent and add tests  | 
86  | 
|
87  | 
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.  | 
88  | 
content = self._make_content([])  | 
| 
2151.1.1
by John Arbash Meinel
 (Dmitry Vasiliev) Tune KnitContent and add tests  | 
89  | 
|
90  | 
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.  | 
91  | 
content = self._make_content([])  | 
| 
2151.1.1
by John Arbash Meinel
 (Dmitry Vasiliev) Tune KnitContent and add tests  | 
92  | 
self.assertEqual(content.text(), [])  | 
93  | 
||
| 
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.  | 
94  | 
content = self._make_content([("origin1", "text1"), ("origin2", "text2")])  | 
| 
2151.1.1
by John Arbash Meinel
 (Dmitry Vasiliev) Tune KnitContent and add tests  | 
95  | 
self.assertEqual(content.text(), ["text1", "text2"])  | 
96  | 
||
| 
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.  | 
97  | 
def test_copy(self):  | 
98  | 
content = self._make_content([("origin1", "text1"), ("origin2", "text2")])  | 
|
99  | 
copy = content.copy()  | 
|
100  | 
self.assertIsInstance(copy, content.__class__)  | 
|
101  | 
self.assertEqual(copy.annotate(), content.annotate())  | 
|
102  | 
||
103  | 
def assertDerivedBlocksEqual(self, source, target, noeol=False):  | 
|
104  | 
"""Assert that the derived matching blocks match real output"""  | 
|
105  | 
source_lines = source.splitlines(True)  | 
|
106  | 
target_lines = target.splitlines(True)  | 
|
107  | 
def nl(line):  | 
|
108  | 
if noeol and not line.endswith('\n'):  | 
|
109  | 
return line + '\n'  | 
|
110  | 
else:  | 
|
111  | 
return line  | 
|
112  | 
source_content = self._make_content([(None, nl(l)) for l in source_lines])  | 
|
113  | 
target_content = self._make_content([(None, nl(l)) for l in target_lines])  | 
|
114  | 
line_delta = source_content.line_delta(target_content)  | 
|
115  | 
delta_blocks = list(KnitContent.get_line_delta_blocks(line_delta,  | 
|
116  | 
source_lines, target_lines))  | 
|
117  | 
matcher = KnitSequenceMatcher(None, source_lines, target_lines)  | 
|
118  | 
matcher_blocks = list(list(matcher.get_matching_blocks()))  | 
|
119  | 
self.assertEqual(matcher_blocks, delta_blocks)  | 
|
120  | 
||
121  | 
def test_get_line_delta_blocks(self):  | 
|
122  | 
self.assertDerivedBlocksEqual('a\nb\nc\n', 'q\nc\n')  | 
|
123  | 
self.assertDerivedBlocksEqual(TEXT_1, TEXT_1)  | 
|
124  | 
self.assertDerivedBlocksEqual(TEXT_1, TEXT_1A)  | 
|
125  | 
self.assertDerivedBlocksEqual(TEXT_1, TEXT_1B)  | 
|
126  | 
self.assertDerivedBlocksEqual(TEXT_1B, TEXT_1A)  | 
|
127  | 
self.assertDerivedBlocksEqual(TEXT_1A, TEXT_1B)  | 
|
128  | 
self.assertDerivedBlocksEqual(TEXT_1A, '')  | 
|
129  | 
self.assertDerivedBlocksEqual('', TEXT_1A)  | 
|
130  | 
self.assertDerivedBlocksEqual('', '')  | 
|
131  | 
self.assertDerivedBlocksEqual('a\nb\nc', 'a\nb\nc\nd')  | 
|
132  | 
||
133  | 
def test_get_line_delta_blocks_noeol(self):  | 
|
134  | 
"""Handle historical knit deltas safely  | 
|
135  | 
||
136  | 
        Some existing knit deltas don't consider the last line to differ
 | 
|
137  | 
        when the only difference whether it has a final newline.
 | 
|
138  | 
||
139  | 
        New knit deltas appear to always consider the last line to differ
 | 
|
140  | 
        in this case.
 | 
|
141  | 
        """
 | 
|
142  | 
self.assertDerivedBlocksEqual('a\nb\nc', 'a\nb\nc\nd\n', noeol=True)  | 
|
143  | 
self.assertDerivedBlocksEqual('a\nb\nc\nd\n', 'a\nb\nc', noeol=True)  | 
|
144  | 
self.assertDerivedBlocksEqual('a\nb\nc\n', 'a\nb\nc', noeol=True)  | 
|
145  | 
self.assertDerivedBlocksEqual('a\nb\nc', 'a\nb\nc\n', noeol=True)  | 
|
146  | 
||
147  | 
||
| 
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.  | 
148  | 
TEXT_1 = """\  | 
149  | 
Banana cup cakes:
 | 
|
150  | 
||
151  | 
- bananas
 | 
|
152  | 
- eggs
 | 
|
153  | 
- broken tea cups
 | 
|
154  | 
"""
 | 
|
155  | 
||
156  | 
TEXT_1A = """\  | 
|
157  | 
Banana cup cake recipe
 | 
|
158  | 
(serves 6)
 | 
|
159  | 
||
160  | 
- bananas
 | 
|
161  | 
- eggs
 | 
|
162  | 
- broken tea cups
 | 
|
163  | 
- self-raising flour
 | 
|
164  | 
"""
 | 
|
165  | 
||
166  | 
TEXT_1B = """\  | 
|
167  | 
Banana cup cake recipe
 | 
|
168  | 
||
169  | 
- bananas (do not use plantains!!!)
 | 
|
170  | 
- broken tea cups
 | 
|
171  | 
- flour
 | 
|
172  | 
"""
 | 
|
173  | 
||
174  | 
delta_1_1a = """\  | 
|
175  | 
0,1,2
 | 
|
176  | 
Banana cup cake recipe
 | 
|
177  | 
(serves 6)
 | 
|
178  | 
5,5,1
 | 
|
179  | 
- self-raising flour
 | 
|
180  | 
"""
 | 
|
181  | 
||
182  | 
TEXT_2 = """\  | 
|
183  | 
Boeuf bourguignon
 | 
|
184  | 
||
185  | 
- beef
 | 
|
186  | 
- red wine
 | 
|
187  | 
- small onions
 | 
|
188  | 
- carrot
 | 
|
189  | 
- mushrooms
 | 
|
190  | 
"""
 | 
|
191  | 
||
192  | 
||
| 
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.  | 
193  | 
class TestPlainKnitContent(TestCase, KnitContentTestsMixin):  | 
194  | 
||
195  | 
def _make_content(self, lines):  | 
|
196  | 
annotated_content = AnnotatedKnitContent(lines)  | 
|
197  | 
return PlainKnitContent(annotated_content.text(), 'bogus')  | 
|
198  | 
||
199  | 
def test_annotate(self):  | 
|
200  | 
content = self._make_content([])  | 
|
201  | 
self.assertEqual(content.annotate(), [])  | 
|
202  | 
||
203  | 
content = self._make_content([("origin1", "text1"), ("origin2", "text2")])  | 
|
204  | 
self.assertEqual(content.annotate(),  | 
|
205  | 
[("bogus", "text1"), ("bogus", "text2")])  | 
|
206  | 
||
207  | 
def test_line_delta(self):  | 
|
208  | 
content1 = self._make_content([("", "a"), ("", "b")])  | 
|
209  | 
content2 = self._make_content([("", "a"), ("", "a"), ("", "c")])  | 
|
210  | 
self.assertEqual(content1.line_delta(content2),  | 
|
211  | 
[(1, 2, 2, ["a", "c"])])  | 
|
212  | 
||
213  | 
def test_line_delta_iter(self):  | 
|
214  | 
content1 = self._make_content([("", "a"), ("", "b")])  | 
|
215  | 
content2 = self._make_content([("", "a"), ("", "a"), ("", "c")])  | 
|
216  | 
it = content1.line_delta_iter(content2)  | 
|
217  | 
self.assertEqual(it.next(), (1, 2, 2, ["a", "c"]))  | 
|
218  | 
self.assertRaises(StopIteration, it.next)  | 
|
219  | 
||
220  | 
||
221  | 
class TestAnnotatedKnitContent(TestCase, KnitContentTestsMixin):  | 
|
222  | 
||
223  | 
def _make_content(self, lines):  | 
|
224  | 
return AnnotatedKnitContent(lines)  | 
|
225  | 
||
226  | 
def test_annotate(self):  | 
|
227  | 
content = self._make_content([])  | 
|
228  | 
self.assertEqual(content.annotate(), [])  | 
|
229  | 
||
230  | 
content = self._make_content([("origin1", "text1"), ("origin2", "text2")])  | 
|
| 
2151.1.1
by John Arbash Meinel
 (Dmitry Vasiliev) Tune KnitContent and add tests  | 
231  | 
self.assertEqual(content.annotate(),  | 
232  | 
[("origin1", "text1"), ("origin2", "text2")])  | 
|
233  | 
||
234  | 
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.  | 
235  | 
content1 = self._make_content([("", "a"), ("", "b")])  | 
236  | 
content2 = self._make_content([("", "a"), ("", "a"), ("", "c")])  | 
|
| 
2151.1.1
by John Arbash Meinel
 (Dmitry Vasiliev) Tune KnitContent and add tests  | 
237  | 
self.assertEqual(content1.line_delta(content2),  | 
238  | 
[(1, 2, 2, [("", "a"), ("", "c")])])  | 
|
239  | 
||
240  | 
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.  | 
241  | 
content1 = self._make_content([("", "a"), ("", "b")])  | 
242  | 
content2 = self._make_content([("", "a"), ("", "a"), ("", "c")])  | 
|
| 
2151.1.1
by John Arbash Meinel
 (Dmitry Vasiliev) Tune KnitContent and add tests  | 
243  | 
it = content1.line_delta_iter(content2)  | 
244  | 
self.assertEqual(it.next(), (1, 2, 2, [("", "a"), ("", "c")]))  | 
|
245  | 
self.assertRaises(StopIteration, it.next)  | 
|
246  | 
||
| 
2158.3.1
by Dmitry Vasiliev
 KnitIndex tests/fixes/optimizations  | 
247  | 
|
248  | 
class MockTransport(object):  | 
|
249  | 
||
250  | 
def __init__(self, file_lines=None):  | 
|
251  | 
self.file_lines = file_lines  | 
|
252  | 
self.calls = []  | 
|
| 
2196.2.3
by John Arbash Meinel
 Update tests and code to pass after merging bzr.dev  | 
253  | 
        # We have no base directory for the MockTransport
 | 
254  | 
self.base = ''  | 
|
| 
2158.3.1
by Dmitry Vasiliev
 KnitIndex tests/fixes/optimizations  | 
255  | 
|
256  | 
def get(self, filename):  | 
|
257  | 
if self.file_lines is None:  | 
|
258  | 
raise NoSuchFile(filename)  | 
|
259  | 
else:  | 
|
260  | 
return StringIO("\n".join(self.file_lines))  | 
|
261  | 
||
| 
2329.1.1
by John Arbash Meinel
 Update _KnitData parser to raise more helpful errors when it detects corruption.  | 
262  | 
def readv(self, relpath, offsets):  | 
263  | 
fp = self.get(relpath)  | 
|
264  | 
for offset, size in offsets:  | 
|
265  | 
fp.seek(offset)  | 
|
266  | 
yield offset, fp.read(size)  | 
|
267  | 
||
| 
2158.3.1
by Dmitry Vasiliev
 KnitIndex tests/fixes/optimizations  | 
268  | 
def __getattr__(self, name):  | 
269  | 
def queue_call(*args, **kwargs):  | 
|
270  | 
self.calls.append((name, args, kwargs))  | 
|
271  | 
return queue_call  | 
|
272  | 
||
273  | 
||
| 
3789.2.2
by John Arbash Meinel
 Test that a readv() failing after yielding data will still raise Retry  | 
274  | 
class MockReadvFailingTransport(MockTransport):  | 
275  | 
"""Fail in the middle of a readv() result.  | 
|
276  | 
||
| 
3789.2.3
by John Arbash Meinel
 Change the mocking a bit, so we can be sure it is failing at the right time.  | 
277  | 
    This Transport will successfully yield the first two requested hunks, but
 | 
278  | 
    raise NoSuchFile for the rest.
 | 
|
| 
3789.2.2
by John Arbash Meinel
 Test that a readv() failing after yielding data will still raise Retry  | 
279  | 
    """
 | 
280  | 
||
281  | 
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.  | 
282  | 
count = 0  | 
| 
3789.2.2
by John Arbash Meinel
 Test that a readv() failing after yielding data will still raise Retry  | 
283  | 
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.  | 
284  | 
count += 1  | 
285  | 
            # we use 2 because the first offset is the pack header, the second
 | 
|
286  | 
            # is the first actual content requset
 | 
|
287  | 
if count > 2:  | 
|
| 
3789.2.2
by John Arbash Meinel
 Test that a readv() failing after yielding data will still raise Retry  | 
288  | 
raise errors.NoSuchFile(relpath)  | 
289  | 
yield result  | 
|
290  | 
||
291  | 
||
| 
2592.3.66
by Robert Collins
 Allow adaption of KnitData to pack files.  | 
292  | 
class KnitRecordAccessTestsMixin(object):  | 
293  | 
"""Tests for getting and putting knit records."""  | 
|
294  | 
||
295  | 
def test_add_raw_records(self):  | 
|
296  | 
"""Add_raw_records adds records retrievable later."""  | 
|
297  | 
access = self.get_access()  | 
|
| 
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.  | 
298  | 
memos = access.add_raw_records([('key', 10)], '1234567890')  | 
| 
2592.3.66
by Robert Collins
 Allow adaption of KnitData to pack files.  | 
299  | 
self.assertEqual(['1234567890'], list(access.get_raw_records(memos)))  | 
| 
2592.3.67
by Robert Collins
 More tests for bzrlib.knit._PackAccess.  | 
300  | 
|
301  | 
def test_add_several_raw_records(self):  | 
|
302  | 
"""add_raw_records with many records and read some back."""  | 
|
303  | 
access = self.get_access()  | 
|
| 
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.  | 
304  | 
memos = access.add_raw_records([('key', 10), ('key2', 2), ('key3', 5)],  | 
305  | 
'12345678901234567')  | 
|
| 
2592.3.67
by Robert Collins
 More tests for bzrlib.knit._PackAccess.  | 
306  | 
self.assertEqual(['1234567890', '12', '34567'],  | 
307  | 
list(access.get_raw_records(memos)))  | 
|
308  | 
self.assertEqual(['1234567890'],  | 
|
309  | 
list(access.get_raw_records(memos[0:1])))  | 
|
310  | 
self.assertEqual(['12'],  | 
|
311  | 
list(access.get_raw_records(memos[1:2])))  | 
|
312  | 
self.assertEqual(['34567'],  | 
|
313  | 
list(access.get_raw_records(memos[2:3])))  | 
|
314  | 
self.assertEqual(['1234567890', '34567'],  | 
|
315  | 
list(access.get_raw_records(memos[0:1] + memos[2:3])))  | 
|
316  | 
||
| 
2592.3.66
by Robert Collins
 Allow adaption of KnitData to pack files.  | 
317  | 
|
318  | 
class TestKnitKnitAccess(TestCaseWithMemoryTransport, KnitRecordAccessTestsMixin):  | 
|
319  | 
"""Tests for the .kndx implementation."""  | 
|
320  | 
||
321  | 
def get_access(self):  | 
|
322  | 
"""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.  | 
323  | 
mapper = ConstantMapper("foo")  | 
324  | 
access = _KnitKeyAccess(self.get_transport(), mapper)  | 
|
| 
2592.3.66
by Robert Collins
 Allow adaption of KnitData to pack files.  | 
325  | 
return access  | 
| 
3789.2.6
by John Arbash Meinel
 Make _DirectPackAccess.reload_or_raise maintain the logic.  | 
326  | 
|
327  | 
||
328  | 
class _TestException(Exception):  | 
|
329  | 
"""Just an exception for local tests to use."""  | 
|
330  | 
||
| 
2592.3.66
by Robert Collins
 Allow adaption of KnitData to pack files.  | 
331  | 
|
332  | 
class TestPackKnitAccess(TestCaseWithMemoryTransport, KnitRecordAccessTestsMixin):  | 
|
333  | 
"""Tests for the pack based access."""  | 
|
334  | 
||
335  | 
def get_access(self):  | 
|
| 
2592.3.67
by Robert Collins
 More tests for bzrlib.knit._PackAccess.  | 
336  | 
return self._get_access()[0]  | 
337  | 
||
338  | 
def _get_access(self, packname='packfile', index='FOO'):  | 
|
| 
2592.3.66
by Robert Collins
 Allow adaption of KnitData to pack files.  | 
339  | 
transport = self.get_transport()  | 
340  | 
def write_data(bytes):  | 
|
| 
2592.3.67
by Robert Collins
 More tests for bzrlib.knit._PackAccess.  | 
341  | 
transport.append_bytes(packname, bytes)  | 
| 
2592.3.66
by Robert Collins
 Allow adaption of KnitData to pack files.  | 
342  | 
writer = pack.ContainerWriter(write_data)  | 
343  | 
writer.begin()  | 
|
| 
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.  | 
344  | 
access = _DirectPackAccess({})  | 
345  | 
access.set_writer(writer, index, (transport, packname))  | 
|
| 
2592.3.67
by Robert Collins
 More tests for bzrlib.knit._PackAccess.  | 
346  | 
return access, writer  | 
| 
2592.3.66
by Robert Collins
 Allow adaption of KnitData to pack files.  | 
347  | 
|
| 
3789.2.5
by John Arbash Meinel
 Change _DirectPackAccess to only raise Retry when _reload_func is defined.  | 
348  | 
def make_pack_file(self):  | 
349  | 
"""Create a pack file with 2 records."""  | 
|
350  | 
access, writer = self._get_access(packname='packname', index='foo')  | 
|
351  | 
memos = []  | 
|
352  | 
memos.extend(access.add_raw_records([('key1', 10)], '1234567890'))  | 
|
353  | 
memos.extend(access.add_raw_records([('key2', 5)], '12345'))  | 
|
354  | 
writer.end()  | 
|
355  | 
return memos  | 
|
356  | 
||
| 
3789.2.11
by John Arbash Meinel
 KnitVersionedFile.get_record_stream now retries *and* fails correctly.  | 
357  | 
def make_vf_for_retrying(self):  | 
| 
3789.2.10
by John Arbash Meinel
 The first function for KnitVersionedFiles can now retry on request.  | 
358  | 
"""Create 3 packs and a reload function.  | 
359  | 
||
360  | 
        Originally, 2 pack files will have the data, but one will be missing.
 | 
|
361  | 
        And then the third will be used in place of the first two if reload()
 | 
|
362  | 
        is called.
 | 
|
363  | 
||
364  | 
        :return: (versioned_file, reload_counter)
 | 
|
365  | 
            versioned_file  a KnitVersionedFiles using the packs for access
 | 
|
366  | 
        """
 | 
|
367  | 
tree = self.make_branch_and_memory_tree('tree')  | 
|
368  | 
tree.lock_write()  | 
|
369  | 
try:  | 
|
370  | 
tree.add([''], ['root-id'])  | 
|
371  | 
tree.commit('one', rev_id='rev-1')  | 
|
372  | 
tree.commit('two', rev_id='rev-2')  | 
|
| 
3789.2.12
by John Arbash Meinel
 iter_lines_added_or_present now retries.  | 
373  | 
tree.commit('three', rev_id='rev-3')  | 
| 
3789.2.10
by John Arbash Meinel
 The first function for KnitVersionedFiles can now retry on request.  | 
374  | 
            # Pack these two revisions into another pack file, but don't remove
 | 
375  | 
            # the originials
 | 
|
376  | 
repo = tree.branch.repository  | 
|
377  | 
collection = repo._pack_collection  | 
|
378  | 
collection.ensure_loaded()  | 
|
379  | 
orig_packs = collection.packs  | 
|
380  | 
packer = pack_repo.Packer(collection, orig_packs, '.testpack')  | 
|
381  | 
new_pack = packer.pack()  | 
|
382  | 
||
383  | 
vf = tree.branch.repository.revisions  | 
|
384  | 
finally:  | 
|
385  | 
tree.unlock()  | 
|
386  | 
tree.branch.repository.lock_read()  | 
|
387  | 
self.addCleanup(tree.branch.repository.unlock)  | 
|
388  | 
del tree  | 
|
389  | 
        # Set up a reload() function that switches to using the new pack file
 | 
|
390  | 
new_index = new_pack.revision_index  | 
|
391  | 
access_tuple = new_pack.access_tuple()  | 
|
392  | 
reload_counter = [0, 0, 0]  | 
|
393  | 
def reload():  | 
|
394  | 
reload_counter[0] += 1  | 
|
395  | 
if reload_counter[1] > 0:  | 
|
396  | 
                # We already reloaded, nothing more to do
 | 
|
397  | 
reload_counter[2] += 1  | 
|
398  | 
return False  | 
|
399  | 
reload_counter[1] += 1  | 
|
400  | 
vf._index._graph_index._indices[:] = [new_index]  | 
|
401  | 
vf._access._indices.clear()  | 
|
402  | 
vf._access._indices[new_index] = access_tuple  | 
|
403  | 
return True  | 
|
| 
3789.2.11
by John Arbash Meinel
 KnitVersionedFile.get_record_stream now retries *and* fails correctly.  | 
404  | 
        # 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.  | 
405  | 
        # 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.  | 
406  | 
trans, name = orig_packs[1].access_tuple()  | 
407  | 
trans.delete(name)  | 
|
408  | 
        # We don't have the index trigger reloading because we want to test
 | 
|
409  | 
        # that we reload when the .pack disappears
 | 
|
410  | 
vf._access._reload_func = reload  | 
|
411  | 
return vf, reload_counter  | 
|
412  | 
||
| 
3789.2.6
by John Arbash Meinel
 Make _DirectPackAccess.reload_or_raise maintain the logic.  | 
413  | 
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.  | 
414  | 
reload_called = [0]  | 
415  | 
def reload():  | 
|
416  | 
reload_called[0] += 1  | 
|
| 
3789.2.6
by John Arbash Meinel
 Make _DirectPackAccess.reload_or_raise maintain the logic.  | 
417  | 
return return_val  | 
| 
3789.2.5
by John Arbash Meinel
 Change _DirectPackAccess to only raise Retry when _reload_func is defined.  | 
418  | 
return reload_called, reload  | 
419  | 
||
| 
3789.2.6
by John Arbash Meinel
 Make _DirectPackAccess.reload_or_raise maintain the logic.  | 
420  | 
def make_retry_exception(self):  | 
421  | 
        # We raise a real exception so that sys.exc_info() is properly
 | 
|
422  | 
        # populated
 | 
|
423  | 
try:  | 
|
424  | 
raise _TestException('foobar')  | 
|
425  | 
except _TestException, e:  | 
|
| 
3789.2.29
by John Arbash Meinel
 RetryWithNewPacks requires another argument.  | 
426  | 
retry_exc = errors.RetryWithNewPacks(None, reload_occurred=False,  | 
| 
3789.2.6
by John Arbash Meinel
 Make _DirectPackAccess.reload_or_raise maintain the logic.  | 
427  | 
exc_info=sys.exc_info())  | 
428  | 
return retry_exc  | 
|
429  | 
||
| 
2592.3.67
by Robert Collins
 More tests for bzrlib.knit._PackAccess.  | 
430  | 
def test_read_from_several_packs(self):  | 
431  | 
access, writer = self._get_access()  | 
|
432  | 
memos = []  | 
|
| 
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.  | 
433  | 
memos.extend(access.add_raw_records([('key', 10)], '1234567890'))  | 
| 
2592.3.67
by Robert Collins
 More tests for bzrlib.knit._PackAccess.  | 
434  | 
writer.end()  | 
435  | 
access, writer = self._get_access('pack2', 'FOOBAR')  | 
|
| 
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.  | 
436  | 
memos.extend(access.add_raw_records([('key', 5)], '12345'))  | 
| 
2592.3.67
by Robert Collins
 More tests for bzrlib.knit._PackAccess.  | 
437  | 
writer.end()  | 
438  | 
access, writer = self._get_access('pack3', 'BAZ')  | 
|
| 
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.  | 
439  | 
memos.extend(access.add_raw_records([('key', 5)], 'alpha'))  | 
| 
2592.3.67
by Robert Collins
 More tests for bzrlib.knit._PackAccess.  | 
440  | 
writer.end()  | 
441  | 
transport = self.get_transport()  | 
|
| 
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.  | 
442  | 
access = _DirectPackAccess({"FOO":(transport, 'packfile'),  | 
| 
2592.3.67
by Robert Collins
 More tests for bzrlib.knit._PackAccess.  | 
443  | 
"FOOBAR":(transport, 'pack2'),  | 
444  | 
"BAZ":(transport, 'pack3')})  | 
|
445  | 
self.assertEqual(['1234567890', '12345', 'alpha'],  | 
|
446  | 
list(access.get_raw_records(memos)))  | 
|
447  | 
self.assertEqual(['1234567890'],  | 
|
448  | 
list(access.get_raw_records(memos[0:1])))  | 
|
449  | 
self.assertEqual(['12345'],  | 
|
450  | 
list(access.get_raw_records(memos[1:2])))  | 
|
451  | 
self.assertEqual(['alpha'],  | 
|
452  | 
list(access.get_raw_records(memos[2:3])))  | 
|
453  | 
self.assertEqual(['1234567890', 'alpha'],  | 
|
454  | 
list(access.get_raw_records(memos[0:1] + memos[2:3])))  | 
|
| 
2592.3.66
by Robert Collins
 Allow adaption of KnitData to pack files.  | 
455  | 
|
| 
2592.3.70
by Robert Collins
 Allow setting a writer after creating a knit._PackAccess object.  | 
456  | 
def test_set_writer(self):  | 
457  | 
"""The writer should be settable post construction."""  | 
|
| 
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.  | 
458  | 
access = _DirectPackAccess({})  | 
| 
2592.3.70
by Robert Collins
 Allow setting a writer after creating a knit._PackAccess object.  | 
459  | 
transport = self.get_transport()  | 
460  | 
packname = 'packfile'  | 
|
461  | 
index = 'foo'  | 
|
462  | 
def write_data(bytes):  | 
|
463  | 
transport.append_bytes(packname, bytes)  | 
|
464  | 
writer = pack.ContainerWriter(write_data)  | 
|
465  | 
writer.begin()  | 
|
466  | 
access.set_writer(writer, index, (transport, packname))  | 
|
| 
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.  | 
467  | 
memos = access.add_raw_records([('key', 10)], '1234567890')  | 
| 
2592.3.70
by Robert Collins
 Allow setting a writer after creating a knit._PackAccess object.  | 
468  | 
writer.end()  | 
469  | 
self.assertEqual(['1234567890'], list(access.get_raw_records(memos)))  | 
|
470  | 
||
| 
3789.2.1
by John Arbash Meinel
 _DirectPackAccess can now raise RetryWithNewPacks when we think something has happened.  | 
471  | 
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.  | 
472  | 
memos = self.make_pack_file()  | 
| 
3789.2.1
by John Arbash Meinel
 _DirectPackAccess can now raise RetryWithNewPacks when we think something has happened.  | 
473  | 
transport = self.get_transport()  | 
| 
3789.2.5
by John Arbash Meinel
 Change _DirectPackAccess to only raise Retry when _reload_func is defined.  | 
474  | 
reload_called, reload_func = self.make_reload_func()  | 
475  | 
        # Note that the index key has changed from 'foo' to 'bar'
 | 
|
476  | 
access = _DirectPackAccess({'bar':(transport, 'packname')},  | 
|
477  | 
reload_func=reload_func)  | 
|
| 
3789.2.1
by John Arbash Meinel
 _DirectPackAccess can now raise RetryWithNewPacks when we think something has happened.  | 
478  | 
e = self.assertListRaises(errors.RetryWithNewPacks,  | 
479  | 
access.get_raw_records, memos)  | 
|
480  | 
        # Because a key was passed in which does not match our index list, we
 | 
|
481  | 
        # assume that the listing was already reloaded
 | 
|
482  | 
self.assertTrue(e.reload_occurred)  | 
|
483  | 
self.assertIsInstance(e.exc_info, tuple)  | 
|
484  | 
self.assertIs(e.exc_info[0], KeyError)  | 
|
485  | 
self.assertIsInstance(e.exc_info[1], KeyError)  | 
|
486  | 
||
| 
3789.2.5
by John Arbash Meinel
 Change _DirectPackAccess to only raise Retry when _reload_func is defined.  | 
487  | 
def test_missing_index_raises_key_error_with_no_reload(self):  | 
488  | 
memos = self.make_pack_file()  | 
|
489  | 
transport = self.get_transport()  | 
|
490  | 
        # Note that the index key has changed from 'foo' to 'bar'
 | 
|
491  | 
access = _DirectPackAccess({'bar':(transport, 'packname')})  | 
|
492  | 
e = self.assertListRaises(KeyError, access.get_raw_records, memos)  | 
|
493  | 
||
| 
3789.2.1
by John Arbash Meinel
 _DirectPackAccess can now raise RetryWithNewPacks when we think something has happened.  | 
494  | 
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.  | 
495  | 
memos = self.make_pack_file()  | 
496  | 
transport = self.get_transport()  | 
|
497  | 
reload_called, reload_func = self.make_reload_func()  | 
|
498  | 
        # Note that the 'filename' has been changed to 'different-packname'
 | 
|
499  | 
access = _DirectPackAccess({'foo':(transport, 'different-packname')},  | 
|
500  | 
reload_func=reload_func)  | 
|
501  | 
e = self.assertListRaises(errors.RetryWithNewPacks,  | 
|
502  | 
access.get_raw_records, memos)  | 
|
503  | 
        # The file has gone missing, so we assume we need to reload
 | 
|
504  | 
self.assertFalse(e.reload_occurred)  | 
|
505  | 
self.assertIsInstance(e.exc_info, tuple)  | 
|
506  | 
self.assertIs(e.exc_info[0], errors.NoSuchFile)  | 
|
507  | 
self.assertIsInstance(e.exc_info[1], errors.NoSuchFile)  | 
|
508  | 
self.assertEqual('different-packname', e.exc_info[1].path)  | 
|
509  | 
||
510  | 
def test_missing_file_raises_no_such_file_with_no_reload(self):  | 
|
511  | 
memos = self.make_pack_file()  | 
|
512  | 
transport = self.get_transport()  | 
|
513  | 
        # Note that the 'filename' has been changed to 'different-packname'
 | 
|
| 
3789.2.1
by John Arbash Meinel
 _DirectPackAccess can now raise RetryWithNewPacks when we think something has happened.  | 
514  | 
access = _DirectPackAccess({'foo':(transport, 'different-packname')})  | 
| 
3789.2.5
by John Arbash Meinel
 Change _DirectPackAccess to only raise Retry when _reload_func is defined.  | 
515  | 
e = self.assertListRaises(errors.NoSuchFile,  | 
| 
3789.2.1
by John Arbash Meinel
 _DirectPackAccess can now raise RetryWithNewPacks when we think something has happened.  | 
516  | 
access.get_raw_records, memos)  | 
517  | 
||
| 
3789.2.2
by John Arbash Meinel
 Test that a readv() failing after yielding data will still raise Retry  | 
518  | 
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.  | 
519  | 
memos = self.make_pack_file()  | 
520  | 
transport = self.get_transport()  | 
|
521  | 
failing_transport = MockReadvFailingTransport(  | 
|
522  | 
[transport.get_bytes('packname')])  | 
|
523  | 
reload_called, reload_func = self.make_reload_func()  | 
|
524  | 
access = _DirectPackAccess({'foo':(failing_transport, 'packname')},  | 
|
525  | 
reload_func=reload_func)  | 
|
526  | 
        # Asking for a single record will not trigger the Mock failure
 | 
|
527  | 
self.assertEqual(['1234567890'],  | 
|
528  | 
list(access.get_raw_records(memos[:1])))  | 
|
529  | 
self.assertEqual(['12345'],  | 
|
530  | 
list(access.get_raw_records(memos[1:2])))  | 
|
531  | 
        # A multiple offset readv() will fail mid-way through
 | 
|
532  | 
e = self.assertListRaises(errors.RetryWithNewPacks,  | 
|
533  | 
access.get_raw_records, memos)  | 
|
534  | 
        # The file has gone missing, so we assume we need to reload
 | 
|
535  | 
self.assertFalse(e.reload_occurred)  | 
|
536  | 
self.assertIsInstance(e.exc_info, tuple)  | 
|
537  | 
self.assertIs(e.exc_info[0], errors.NoSuchFile)  | 
|
538  | 
self.assertIsInstance(e.exc_info[1], errors.NoSuchFile)  | 
|
539  | 
self.assertEqual('packname', e.exc_info[1].path)  | 
|
540  | 
||
541  | 
def test_failing_readv_raises_no_such_file_with_no_reload(self):  | 
|
542  | 
memos = self.make_pack_file()  | 
|
543  | 
transport = self.get_transport()  | 
|
544  | 
failing_transport = MockReadvFailingTransport(  | 
|
545  | 
[transport.get_bytes('packname')])  | 
|
546  | 
reload_called, reload_func = self.make_reload_func()  | 
|
| 
3789.2.2
by John Arbash Meinel
 Test that a readv() failing after yielding data will still raise Retry  | 
547  | 
access = _DirectPackAccess({'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.  | 
548  | 
        # Asking for a single record will not trigger the Mock failure
 | 
549  | 
self.assertEqual(['1234567890'],  | 
|
550  | 
list(access.get_raw_records(memos[:1])))  | 
|
551  | 
self.assertEqual(['12345'],  | 
|
552  | 
list(access.get_raw_records(memos[1:2])))  | 
|
553  | 
        # 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.  | 
554  | 
e = self.assertListRaises(errors.NoSuchFile,  | 
| 
3789.2.2
by John Arbash Meinel
 Test that a readv() failing after yielding data will still raise Retry  | 
555  | 
access.get_raw_records, memos)  | 
556  | 
||
| 
3789.2.6
by John Arbash Meinel
 Make _DirectPackAccess.reload_or_raise maintain the logic.  | 
557  | 
def test_reload_or_raise_no_reload(self):  | 
558  | 
access = _DirectPackAccess({}, reload_func=None)  | 
|
559  | 
retry_exc = self.make_retry_exception()  | 
|
560  | 
        # Without a reload_func, we will just re-raise the original exception
 | 
|
561  | 
self.assertRaises(_TestException, access.reload_or_raise, retry_exc)  | 
|
562  | 
||
563  | 
def test_reload_or_raise_reload_changed(self):  | 
|
564  | 
reload_called, reload_func = self.make_reload_func(return_val=True)  | 
|
565  | 
access = _DirectPackAccess({}, reload_func=reload_func)  | 
|
566  | 
retry_exc = self.make_retry_exception()  | 
|
567  | 
access.reload_or_raise(retry_exc)  | 
|
568  | 
self.assertEqual([1], reload_called)  | 
|
569  | 
retry_exc.reload_occurred=True  | 
|
570  | 
access.reload_or_raise(retry_exc)  | 
|
571  | 
self.assertEqual([2], reload_called)  | 
|
572  | 
||
573  | 
def test_reload_or_raise_reload_no_change(self):  | 
|
574  | 
reload_called, reload_func = self.make_reload_func(return_val=False)  | 
|
575  | 
access = _DirectPackAccess({}, reload_func=reload_func)  | 
|
576  | 
retry_exc = self.make_retry_exception()  | 
|
577  | 
        # If reload_occurred is False, then we consider it an error to have
 | 
|
578  | 
        # reload_func() return False (no changes).
 | 
|
579  | 
self.assertRaises(_TestException, access.reload_or_raise, retry_exc)  | 
|
580  | 
self.assertEqual([1], reload_called)  | 
|
581  | 
retry_exc.reload_occurred=True  | 
|
582  | 
        # If reload_occurred is True, then we assume nothing changed because
 | 
|
583  | 
        # it had changed earlier, but didn't change again
 | 
|
584  | 
access.reload_or_raise(retry_exc)  | 
|
585  | 
self.assertEqual([2], reload_called)  | 
|
586  | 
||
| 
3789.2.13
by John Arbash Meinel
 KnitVersionedFile.annotate() now retries when appropriate.  | 
587  | 
def test_annotate_retries(self):  | 
588  | 
vf, reload_counter = self.make_vf_for_retrying()  | 
|
589  | 
        # It is a little bit bogus to annotate the Revision VF, but it works,
 | 
|
590  | 
        # as we have ancestry stored there
 | 
|
591  | 
key = ('rev-3',)  | 
|
592  | 
reload_lines = vf.annotate(key)  | 
|
593  | 
self.assertEqual([1, 1, 0], reload_counter)  | 
|
594  | 
plain_lines = vf.annotate(key)  | 
|
595  | 
self.assertEqual([1, 1, 0], reload_counter) # No extra reloading  | 
|
596  | 
if reload_lines != plain_lines:  | 
|
597  | 
self.fail('Annotation was not identical with reloading.')  | 
|
598  | 
        # Now delete the packs-in-use, which should trigger another reload, but
 | 
|
599  | 
        # this time we just raise an exception because we can't recover
 | 
|
600  | 
for trans, name in vf._access._indices.itervalues():  | 
|
601  | 
trans.delete(name)  | 
|
602  | 
self.assertRaises(errors.NoSuchFile, vf.annotate, key)  | 
|
603  | 
self.assertEqual([2, 1, 1], reload_counter)  | 
|
604  | 
||
| 
3789.2.10
by John Arbash Meinel
 The first function for KnitVersionedFiles can now retry on request.  | 
605  | 
def test__get_record_map_retries(self):  | 
| 
3789.2.11
by John Arbash Meinel
 KnitVersionedFile.get_record_stream now retries *and* fails correctly.  | 
606  | 
vf, reload_counter = self.make_vf_for_retrying()  | 
| 
3789.2.12
by John Arbash Meinel
 iter_lines_added_or_present now retries.  | 
607  | 
keys = [('rev-1',), ('rev-2',), ('rev-3',)]  | 
| 
3789.2.10
by John Arbash Meinel
 The first function for KnitVersionedFiles can now retry on request.  | 
608  | 
records = vf._get_record_map(keys)  | 
609  | 
self.assertEqual(keys, sorted(records.keys()))  | 
|
| 
3789.2.11
by John Arbash Meinel
 KnitVersionedFile.get_record_stream now retries *and* fails correctly.  | 
610  | 
self.assertEqual([1, 1, 0], reload_counter)  | 
611  | 
        # Now delete the packs-in-use, which should trigger another reload, but
 | 
|
612  | 
        # this time we just raise an exception because we can't recover
 | 
|
613  | 
for trans, name in vf._access._indices.itervalues():  | 
|
614  | 
trans.delete(name)  | 
|
615  | 
self.assertRaises(errors.NoSuchFile, vf._get_record_map, keys)  | 
|
616  | 
self.assertEqual([2, 1, 1], reload_counter)  | 
|
617  | 
||
618  | 
def test_get_record_stream_retries(self):  | 
|
619  | 
vf, reload_counter = self.make_vf_for_retrying()  | 
|
| 
3789.2.12
by John Arbash Meinel
 iter_lines_added_or_present now retries.  | 
620  | 
keys = [('rev-1',), ('rev-2',), ('rev-3',)]  | 
| 
3789.2.11
by John Arbash Meinel
 KnitVersionedFile.get_record_stream now retries *and* fails correctly.  | 
621  | 
record_stream = vf.get_record_stream(keys, 'topological', False)  | 
622  | 
record = record_stream.next()  | 
|
623  | 
self.assertEqual(('rev-1',), record.key)  | 
|
624  | 
self.assertEqual([0, 0, 0], reload_counter)  | 
|
625  | 
record = record_stream.next()  | 
|
626  | 
self.assertEqual(('rev-2',), record.key)  | 
|
627  | 
self.assertEqual([1, 1, 0], reload_counter)  | 
|
| 
3789.2.12
by John Arbash Meinel
 iter_lines_added_or_present now retries.  | 
628  | 
record = record_stream.next()  | 
629  | 
self.assertEqual(('rev-3',), record.key)  | 
|
630  | 
self.assertEqual([1, 1, 0], reload_counter)  | 
|
| 
3789.2.11
by John Arbash Meinel
 KnitVersionedFile.get_record_stream now retries *and* fails correctly.  | 
631  | 
        # Now delete all pack files, and see that we raise the right error
 | 
632  | 
for trans, name in vf._access._indices.itervalues():  | 
|
633  | 
trans.delete(name)  | 
|
634  | 
self.assertListRaises(errors.NoSuchFile,  | 
|
635  | 
vf.get_record_stream, keys, 'topological', False)  | 
|
636  | 
||
| 
3789.2.12
by John Arbash Meinel
 iter_lines_added_or_present now retries.  | 
637  | 
def test_iter_lines_added_or_present_in_keys_retries(self):  | 
638  | 
vf, reload_counter = self.make_vf_for_retrying()  | 
|
639  | 
keys = [('rev-1',), ('rev-2',), ('rev-3',)]  | 
|
640  | 
        # Unfortunately, iter_lines_added_or_present_in_keys iterates the
 | 
|
641  | 
        # result in random order (determined by the iteration order from a
 | 
|
642  | 
        # set()), so we don't have any solid way to trigger whether data is
 | 
|
643  | 
        # read before or after. However we tried to delete the middle node to
 | 
|
644  | 
        # exercise the code well.
 | 
|
645  | 
        # What we care about is that all lines are always yielded, but not
 | 
|
646  | 
        # duplicated
 | 
|
647  | 
count = 0  | 
|
648  | 
reload_lines = sorted(vf.iter_lines_added_or_present_in_keys(keys))  | 
|
649  | 
self.assertEqual([1, 1, 0], reload_counter)  | 
|
650  | 
        # Now do it again, to make sure the result is equivalent
 | 
|
651  | 
plain_lines = sorted(vf.iter_lines_added_or_present_in_keys(keys))  | 
|
652  | 
self.assertEqual([1, 1, 0], reload_counter) # No extra reloading  | 
|
653  | 
self.assertEqual(plain_lines, reload_lines)  | 
|
654  | 
self.assertEqual(21, len(plain_lines))  | 
|
655  | 
        # Now delete all pack files, and see that we raise the right error
 | 
|
656  | 
for trans, name in vf._access._indices.itervalues():  | 
|
657  | 
trans.delete(name)  | 
|
658  | 
self.assertListRaises(errors.NoSuchFile,  | 
|
659  | 
vf.iter_lines_added_or_present_in_keys, keys)  | 
|
660  | 
self.assertEqual([2, 1, 1], reload_counter)  | 
|
661  | 
||
| 
3878.1.1
by John Arbash Meinel
 KVF.get_record_stream('unordered') now returns the records based on I/O ordering.  | 
662  | 
def test_get_record_stream_yields_disk_sorted_order(self):  | 
663  | 
        # if we get 'unordered' pick a semi-optimal order for reading. The
 | 
|
664  | 
        # order should be grouped by pack file, and then by position in file
 | 
|
665  | 
repo = self.make_repository('test', format='pack-0.92')  | 
|
666  | 
repo.lock_write()  | 
|
667  | 
self.addCleanup(repo.unlock)  | 
|
668  | 
repo.start_write_group()  | 
|
669  | 
vf = repo.texts  | 
|
670  | 
vf.add_lines(('f-id', 'rev-5'), [('f-id', 'rev-4')], ['lines\n'])  | 
|
671  | 
vf.add_lines(('f-id', 'rev-1'), [], ['lines\n'])  | 
|
672  | 
vf.add_lines(('f-id', 'rev-2'), [('f-id', 'rev-1')], ['lines\n'])  | 
|
673  | 
repo.commit_write_group()  | 
|
674  | 
        # We inserted them as rev-5, rev-1, rev-2, we should get them back in
 | 
|
675  | 
        # the same order
 | 
|
676  | 
stream = vf.get_record_stream([('f-id', 'rev-1'), ('f-id', 'rev-5'),  | 
|
677  | 
('f-id', 'rev-2')], 'unordered', False)  | 
|
678  | 
keys = [r.key for r in stream]  | 
|
679  | 
self.assertEqual([('f-id', 'rev-5'), ('f-id', 'rev-1'),  | 
|
680  | 
('f-id', 'rev-2')], keys)  | 
|
681  | 
repo.start_write_group()  | 
|
682  | 
vf.add_lines(('f-id', 'rev-4'), [('f-id', 'rev-3')], ['lines\n'])  | 
|
683  | 
vf.add_lines(('f-id', 'rev-3'), [('f-id', 'rev-2')], ['lines\n'])  | 
|
684  | 
vf.add_lines(('f-id', 'rev-6'), [('f-id', 'rev-5')], ['lines\n'])  | 
|
685  | 
repo.commit_write_group()  | 
|
686  | 
        # Request in random order, to make sure the output order isn't based on
 | 
|
687  | 
        # the request
 | 
|
688  | 
request_keys = set(('f-id', 'rev-%d' % i) for i in range(1, 7))  | 
|
689  | 
stream = vf.get_record_stream(request_keys, 'unordered', False)  | 
|
690  | 
keys = [r.key for r in stream]  | 
|
691  | 
        # We want to get the keys back in disk order, but it doesn't matter
 | 
|
692  | 
        # which pack we read from first. So this can come back in 2 orders
 | 
|
693  | 
alt1 = [('f-id', 'rev-%d' % i) for i in [4, 3, 6, 5, 1, 2]]  | 
|
694  | 
alt2 = [('f-id', 'rev-%d' % i) for i in [5, 1, 2, 4, 3, 6]]  | 
|
695  | 
if keys != alt1 and keys != alt2:  | 
|
696  | 
self.fail('Returned key order did not match either expected order.'  | 
|
697  | 
' expected %s or %s, not %s'  | 
|
698  | 
% (alt1, alt2, keys))  | 
|
699  | 
||
| 
2592.3.66
by Robert Collins
 Allow adaption of KnitData to pack files.  | 
700  | 
|
| 
2329.1.1
by John Arbash Meinel
 Update _KnitData parser to raise more helpful errors when it detects corruption.  | 
701  | 
class LowLevelKnitDataTests(TestCase):  | 
702  | 
||
703  | 
def create_gz_content(self, text):  | 
|
704  | 
sio = StringIO()  | 
|
705  | 
gz_file = gzip.GzipFile(mode='wb', fileobj=sio)  | 
|
706  | 
gz_file.write(text)  | 
|
707  | 
gz_file.close()  | 
|
708  | 
return sio.getvalue()  | 
|
709  | 
||
| 
3789.2.4
by John Arbash Meinel
 Add a multiple-record test, though it isn't quite what we want for the readv tests.  | 
710  | 
def make_multiple_records(self):  | 
711  | 
"""Create the content for multiple records."""  | 
|
712  | 
sha1sum = osutils.sha('foo\nbar\n').hexdigest()  | 
|
713  | 
total_txt = []  | 
|
714  | 
gz_txt = self.create_gz_content('version rev-id-1 2 %s\n'  | 
|
715  | 
'foo\n'  | 
|
716  | 
'bar\n'  | 
|
717  | 
'end rev-id-1\n'  | 
|
718  | 
% (sha1sum,))  | 
|
719  | 
record_1 = (0, len(gz_txt), sha1sum)  | 
|
720  | 
total_txt.append(gz_txt)  | 
|
721  | 
sha1sum = osutils.sha('baz\n').hexdigest()  | 
|
722  | 
gz_txt = self.create_gz_content('version rev-id-2 1 %s\n'  | 
|
723  | 
'baz\n'  | 
|
724  | 
'end rev-id-2\n'  | 
|
725  | 
% (sha1sum,))  | 
|
726  | 
record_2 = (record_1[1], len(gz_txt), sha1sum)  | 
|
727  | 
total_txt.append(gz_txt)  | 
|
728  | 
return total_txt, record_1, record_2  | 
|
729  | 
||
| 
2329.1.1
by John Arbash Meinel
 Update _KnitData parser to raise more helpful errors when it detects corruption.  | 
730  | 
def test_valid_knit_data(self):  | 
| 
3734.2.4
by Vincent Ladeuil
 Fix python2.6 deprecation warnings related to hashlib.  | 
731  | 
sha1sum = osutils.sha('foo\nbar\n').hexdigest()  | 
| 
2329.1.1
by John Arbash Meinel
 Update _KnitData parser to raise more helpful errors when it detects corruption.  | 
732  | 
gz_txt = self.create_gz_content('version rev-id-1 2 %s\n'  | 
733  | 
'foo\n'  | 
|
734  | 
'bar\n'  | 
|
735  | 
'end rev-id-1\n'  | 
|
736  | 
% (sha1sum,))  | 
|
737  | 
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.  | 
738  | 
access = _KnitKeyAccess(transport, ConstantMapper('filename'))  | 
739  | 
knit = KnitVersionedFiles(None, access)  | 
|
740  | 
records = [(('rev-id-1',), (('rev-id-1',), 0, len(gz_txt)))]  | 
|
741  | 
||
742  | 
contents = list(knit._read_records_iter(records))  | 
|
743  | 
self.assertEqual([(('rev-id-1',), ['foo\n', 'bar\n'],  | 
|
744  | 
'4e48e2c9a3d2ca8a708cb0cc545700544efb5021')], contents)  | 
|
745  | 
||
746  | 
raw_contents = list(knit._read_records_iter_raw(records))  | 
|
747  | 
self.assertEqual([(('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.  | 
748  | 
|
| 
3789.2.4
by John Arbash Meinel
 Add a multiple-record test, though it isn't quite what we want for the readv tests.  | 
749  | 
def test_multiple_records_valid(self):  | 
750  | 
total_txt, record_1, record_2 = self.make_multiple_records()  | 
|
751  | 
transport = MockTransport([''.join(total_txt)])  | 
|
752  | 
access = _KnitKeyAccess(transport, ConstantMapper('filename'))  | 
|
753  | 
knit = KnitVersionedFiles(None, access)  | 
|
754  | 
records = [(('rev-id-1',), (('rev-id-1',), record_1[0], record_1[1])),  | 
|
755  | 
(('rev-id-2',), (('rev-id-2',), record_2[0], record_2[1]))]  | 
|
756  | 
||
757  | 
contents = list(knit._read_records_iter(records))  | 
|
758  | 
self.assertEqual([(('rev-id-1',), ['foo\n', 'bar\n'], record_1[2]),  | 
|
759  | 
(('rev-id-2',), ['baz\n'], record_2[2])],  | 
|
760  | 
contents)  | 
|
761  | 
||
762  | 
raw_contents = list(knit._read_records_iter_raw(records))  | 
|
763  | 
self.assertEqual([(('rev-id-1',), total_txt[0], record_1[2]),  | 
|
764  | 
(('rev-id-2',), total_txt[1], record_2[2])],  | 
|
765  | 
raw_contents)  | 
|
766  | 
||
| 
2329.1.1
by John Arbash Meinel
 Update _KnitData parser to raise more helpful errors when it detects corruption.  | 
767  | 
def test_not_enough_lines(self):  | 
| 
3734.2.4
by Vincent Ladeuil
 Fix python2.6 deprecation warnings related to hashlib.  | 
768  | 
sha1sum = osutils.sha('foo\n').hexdigest()  | 
| 
2329.1.1
by John Arbash Meinel
 Update _KnitData parser to raise more helpful errors when it detects corruption.  | 
769  | 
        # record says 2 lines data says 1
 | 
770  | 
gz_txt = self.create_gz_content('version rev-id-1 2 %s\n'  | 
|
771  | 
'foo\n'  | 
|
772  | 
'end rev-id-1\n'  | 
|
773  | 
% (sha1sum,))  | 
|
774  | 
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.  | 
775  | 
access = _KnitKeyAccess(transport, ConstantMapper('filename'))  | 
776  | 
knit = KnitVersionedFiles(None, access)  | 
|
777  | 
records = [(('rev-id-1',), (('rev-id-1',), 0, len(gz_txt)))]  | 
|
778  | 
self.assertRaises(errors.KnitCorrupt, list,  | 
|
779  | 
knit._read_records_iter(records))  | 
|
| 
2329.1.1
by John Arbash Meinel
 Update _KnitData parser to raise more helpful errors when it detects corruption.  | 
780  | 
|
781  | 
        # 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.  | 
782  | 
raw_contents = list(knit._read_records_iter_raw(records))  | 
783  | 
self.assertEqual([(('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.  | 
784  | 
|
785  | 
def test_too_many_lines(self):  | 
|
| 
3734.2.4
by Vincent Ladeuil
 Fix python2.6 deprecation warnings related to hashlib.  | 
786  | 
sha1sum = osutils.sha('foo\nbar\n').hexdigest()  | 
| 
2329.1.1
by John Arbash Meinel
 Update _KnitData parser to raise more helpful errors when it detects corruption.  | 
787  | 
        # record says 1 lines data says 2
 | 
788  | 
gz_txt = self.create_gz_content('version rev-id-1 1 %s\n'  | 
|
789  | 
'foo\n'  | 
|
790  | 
'bar\n'  | 
|
791  | 
'end rev-id-1\n'  | 
|
792  | 
% (sha1sum,))  | 
|
793  | 
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.  | 
794  | 
access = _KnitKeyAccess(transport, ConstantMapper('filename'))  | 
795  | 
knit = KnitVersionedFiles(None, access)  | 
|
796  | 
records = [(('rev-id-1',), (('rev-id-1',), 0, len(gz_txt)))]  | 
|
797  | 
self.assertRaises(errors.KnitCorrupt, list,  | 
|
798  | 
knit._read_records_iter(records))  | 
|
| 
2329.1.1
by John Arbash Meinel
 Update _KnitData parser to raise more helpful errors when it detects corruption.  | 
799  | 
|
800  | 
        # 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.  | 
801  | 
raw_contents = list(knit._read_records_iter_raw(records))  | 
802  | 
self.assertEqual([(('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.  | 
803  | 
|
804  | 
def test_mismatched_version_id(self):  | 
|
| 
3734.2.4
by Vincent Ladeuil
 Fix python2.6 deprecation warnings related to hashlib.  | 
805  | 
sha1sum = osutils.sha('foo\nbar\n').hexdigest()  | 
| 
2329.1.1
by John Arbash Meinel
 Update _KnitData parser to raise more helpful errors when it detects corruption.  | 
806  | 
gz_txt = self.create_gz_content('version rev-id-1 2 %s\n'  | 
807  | 
'foo\n'  | 
|
808  | 
'bar\n'  | 
|
809  | 
'end rev-id-1\n'  | 
|
810  | 
% (sha1sum,))  | 
|
811  | 
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.  | 
812  | 
access = _KnitKeyAccess(transport, ConstantMapper('filename'))  | 
813  | 
knit = KnitVersionedFiles(None, access)  | 
|
| 
2329.1.1
by John Arbash Meinel
 Update _KnitData parser to raise more helpful errors when it detects corruption.  | 
814  | 
        # We are asking for rev-id-2, but the data is rev-id-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.  | 
815  | 
records = [(('rev-id-2',), (('rev-id-2',), 0, len(gz_txt)))]  | 
816  | 
self.assertRaises(errors.KnitCorrupt, list,  | 
|
817  | 
knit._read_records_iter(records))  | 
|
| 
2329.1.1
by John Arbash Meinel
 Update _KnitData parser to raise more helpful errors when it detects corruption.  | 
818  | 
|
| 
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.  | 
819  | 
        # read_records_iter_raw detects mismatches in the header
 | 
| 
2329.1.1
by John Arbash Meinel
 Update _KnitData parser to raise more helpful errors when it detects corruption.  | 
820  | 
self.assertRaises(errors.KnitCorrupt, list,  | 
| 
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.  | 
821  | 
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.  | 
822  | 
|
823  | 
def test_uncompressed_data(self):  | 
|
| 
3734.2.4
by Vincent Ladeuil
 Fix python2.6 deprecation warnings related to hashlib.  | 
824  | 
sha1sum = osutils.sha('foo\nbar\n').hexdigest()  | 
| 
2329.1.1
by John Arbash Meinel
 Update _KnitData parser to raise more helpful errors when it detects corruption.  | 
825  | 
txt = ('version rev-id-1 2 %s\n'  | 
826  | 
'foo\n'  | 
|
827  | 
'bar\n'  | 
|
828  | 
'end rev-id-1\n'  | 
|
829  | 
% (sha1sum,))  | 
|
830  | 
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.  | 
831  | 
access = _KnitKeyAccess(transport, ConstantMapper('filename'))  | 
832  | 
knit = KnitVersionedFiles(None, access)  | 
|
833  | 
records = [(('rev-id-1',), (('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.  | 
834  | 
|
835  | 
        # We don't have valid gzip data ==> corrupt
 | 
|
| 
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.  | 
836  | 
self.assertRaises(errors.KnitCorrupt, list,  | 
837  | 
knit._read_records_iter(records))  | 
|
| 
2329.1.1
by John Arbash Meinel
 Update _KnitData parser to raise more helpful errors when it detects corruption.  | 
838  | 
|
839  | 
        # read_records_iter_raw will notice the bad data
 | 
|
840  | 
self.assertRaises(errors.KnitCorrupt, list,  | 
|
| 
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.  | 
841  | 
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.  | 
842  | 
|
843  | 
def test_corrupted_data(self):  | 
|
| 
3734.2.4
by Vincent Ladeuil
 Fix python2.6 deprecation warnings related to hashlib.  | 
844  | 
sha1sum = osutils.sha('foo\nbar\n').hexdigest()  | 
| 
2329.1.1
by John Arbash Meinel
 Update _KnitData parser to raise more helpful errors when it detects corruption.  | 
845  | 
gz_txt = self.create_gz_content('version rev-id-1 2 %s\n'  | 
846  | 
'foo\n'  | 
|
847  | 
'bar\n'  | 
|
848  | 
'end rev-id-1\n'  | 
|
849  | 
% (sha1sum,))  | 
|
850  | 
        # Change 2 bytes in the middle to \xff
 | 
|
851  | 
gz_txt = gz_txt[:10] + '\xff\xff' + gz_txt[12:]  | 
|
852  | 
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.  | 
853  | 
access = _KnitKeyAccess(transport, ConstantMapper('filename'))  | 
854  | 
knit = KnitVersionedFiles(None, access)  | 
|
855  | 
records = [(('rev-id-1',), (('rev-id-1',), 0, len(gz_txt)))]  | 
|
856  | 
self.assertRaises(errors.KnitCorrupt, list,  | 
|
857  | 
knit._read_records_iter(records))  | 
|
858  | 
        # read_records_iter_raw will barf on bad gz data
 | 
|
859  | 
self.assertRaises(errors.KnitCorrupt, list,  | 
|
860  | 
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.  | 
861  | 
|
862  | 
||
| 
2158.3.1
by Dmitry Vasiliev
 KnitIndex tests/fixes/optimizations  | 
863  | 
class LowLevelKnitIndexTests(TestCase):  | 
864  | 
||
| 
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.  | 
865  | 
def get_knit_index(self, transport, name, mode):  | 
866  | 
mapper = ConstantMapper(name)  | 
|
| 
2484.1.1
by John Arbash Meinel
 Add an initial function to read knit indexes in pyrex.  | 
867  | 
orig = knit._load_data  | 
868  | 
def reset():  | 
|
869  | 
knit._load_data = orig  | 
|
870  | 
self.addCleanup(reset)  | 
|
| 
2484.1.12
by John Arbash Meinel
 Switch the layout to use a matching _knit_load_data_py.py and _knit_load_data_c.pyx  | 
871  | 
from bzrlib._knit_load_data_py import _load_data_py  | 
872  | 
knit._load_data = _load_data_py  | 
|
| 
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.  | 
873  | 
allow_writes = lambda: 'w' in mode  | 
874  | 
return _KndxIndex(transport, mapper, lambda:None, allow_writes, lambda:True)  | 
|
| 
2158.3.1
by Dmitry Vasiliev
 KnitIndex tests/fixes/optimizations  | 
875  | 
|
876  | 
def test_create_file(self):  | 
|
877  | 
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.  | 
878  | 
index = self.get_knit_index(transport, "filename", "w")  | 
879  | 
index.keys()  | 
|
880  | 
call = transport.calls.pop(0)  | 
|
881  | 
        # call[1][1] is a StringIO - we can't test it by simple equality.
 | 
|
882  | 
self.assertEqual('put_file_non_atomic', call[0])  | 
|
883  | 
self.assertEqual('filename.kndx', call[1][0])  | 
|
884  | 
        # With no history, _KndxIndex writes a new index:
 | 
|
885  | 
self.assertEqual(_KndxIndex.HEADER,  | 
|
886  | 
call[1][1].getvalue())  | 
|
887  | 
self.assertEqual({'create_parent_dir': True}, call[2])  | 
|
| 
2158.3.1
by Dmitry Vasiliev
 KnitIndex tests/fixes/optimizations  | 
888  | 
|
889  | 
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  | 
890  | 
unicode_revision_id = u"version-\N{CYRILLIC CAPITAL LETTER A}"  | 
891  | 
utf8_revision_id = unicode_revision_id.encode('utf-8')  | 
|
| 
2158.3.1
by Dmitry Vasiliev
 KnitIndex tests/fixes/optimizations  | 
892  | 
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.  | 
893  | 
_KndxIndex.HEADER,  | 
| 
2249.5.12
by John Arbash Meinel
 Change the APIs for VersionedFile, Store, and some of Repository into utf-8  | 
894  | 
'%s option 0 1 :' % (utf8_revision_id,)  | 
| 
2158.3.1
by Dmitry Vasiliev
 KnitIndex tests/fixes/optimizations  | 
895  | 
            ])
 | 
| 
2484.1.1
by John Arbash Meinel
 Add an initial function to read knit indexes in pyrex.  | 
896  | 
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.  | 
897  | 
        # _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  | 
898  | 
        # Unicode revision_ids.
 | 
| 
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  | 
self.assertEqual({(utf8_revision_id,):()},  | 
900  | 
index.get_parent_map(index.keys()))  | 
|
901  | 
self.assertFalse((unicode_revision_id,) in index.keys())  | 
|
| 
2158.3.1
by Dmitry Vasiliev
 KnitIndex tests/fixes/optimizations  | 
902  | 
|
903  | 
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  | 
904  | 
unicode_revision_id = u"version-\N{CYRILLIC CAPITAL LETTER A}"  | 
905  | 
utf8_revision_id = unicode_revision_id.encode('utf-8')  | 
|
| 
2158.3.1
by Dmitry Vasiliev
 KnitIndex tests/fixes/optimizations  | 
906  | 
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.  | 
907  | 
_KndxIndex.HEADER,  | 
| 
2249.5.12
by John Arbash Meinel
 Change the APIs for VersionedFile, Store, and some of Repository into utf-8  | 
908  | 
"version option 0 1 .%s :" % (utf8_revision_id,)  | 
| 
2158.3.1
by Dmitry Vasiliev
 KnitIndex tests/fixes/optimizations  | 
909  | 
            ])
 | 
| 
2484.1.1
by John Arbash Meinel
 Add an initial function to read knit indexes in pyrex.  | 
910  | 
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.  | 
911  | 
self.assertEqual({("version",):((utf8_revision_id,),)},  | 
912  | 
index.get_parent_map(index.keys()))  | 
|
| 
2158.3.1
by Dmitry Vasiliev
 KnitIndex tests/fixes/optimizations  | 
913  | 
|
914  | 
def test_read_ignore_corrupted_lines(self):  | 
|
915  | 
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.  | 
916  | 
_KndxIndex.HEADER,  | 
| 
2158.3.1
by Dmitry Vasiliev
 KnitIndex tests/fixes/optimizations  | 
917  | 
"corrupted",  | 
918  | 
"corrupted options 0 1 .b .c ",  | 
|
919  | 
            "version options 0 1 :"
 | 
|
920  | 
            ])
 | 
|
| 
2484.1.1
by John Arbash Meinel
 Add an initial function to read knit indexes in pyrex.  | 
921  | 
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.  | 
922  | 
self.assertEqual(1, len(index.keys()))  | 
923  | 
self.assertEqual(set([("version",)]), index.keys())  | 
|
| 
2158.3.1
by Dmitry Vasiliev
 KnitIndex tests/fixes/optimizations  | 
924  | 
|
925  | 
def test_read_corrupted_header(self):  | 
|
| 
2196.2.3
by John Arbash Meinel
 Update tests and code to pass after merging bzr.dev  | 
926  | 
transport = MockTransport(['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.  | 
927  | 
index = self.get_knit_index(transport, "filename", "r")  | 
928  | 
self.assertRaises(KnitHeaderError, index.keys)  | 
|
| 
2158.3.1
by Dmitry Vasiliev
 KnitIndex tests/fixes/optimizations  | 
929  | 
|
930  | 
def test_read_duplicate_entries(self):  | 
|
931  | 
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.  | 
932  | 
_KndxIndex.HEADER,  | 
| 
2158.3.1
by Dmitry Vasiliev
 KnitIndex tests/fixes/optimizations  | 
933  | 
"parent options 0 1 :",  | 
934  | 
"version options1 0 1 0 :",  | 
|
935  | 
"version options2 1 2 .other :",  | 
|
936  | 
            "version options3 3 4 0 .other :"
 | 
|
937  | 
            ])
 | 
|
| 
2484.1.1
by John Arbash Meinel
 Add an initial function to read knit indexes in pyrex.  | 
938  | 
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.  | 
939  | 
self.assertEqual(2, len(index.keys()))  | 
| 
2592.3.8
by Robert Collins
 Remove unneeded pulib method lookup on private class _KnitIndex.  | 
940  | 
        # check that the index used is the first one written. (Specific
 | 
941  | 
        # to KnitIndex style indices.
 | 
|
| 
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.  | 
942  | 
self.assertEqual("1", index._dictionary_compress([("version",)]))  | 
943  | 
self.assertEqual((("version",), 3, 4), index.get_position(("version",)))  | 
|
944  | 
self.assertEqual(["options3"], index.get_options(("version",)))  | 
|
945  | 
self.assertEqual({("version",):(("parent",), ("other",))},  | 
|
946  | 
index.get_parent_map([("version",)]))  | 
|
| 
2158.3.1
by Dmitry Vasiliev
 KnitIndex tests/fixes/optimizations  | 
947  | 
|
948  | 
def test_read_compressed_parents(self):  | 
|
949  | 
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.  | 
950  | 
_KndxIndex.HEADER,  | 
| 
2158.3.1
by Dmitry Vasiliev
 KnitIndex tests/fixes/optimizations  | 
951  | 
"a option 0 1 :",  | 
952  | 
"b option 0 1 0 :",  | 
|
953  | 
"c option 0 1 1 0 :",  | 
|
954  | 
            ])
 | 
|
| 
2484.1.1
by John Arbash Meinel
 Add an initial function to read knit indexes in pyrex.  | 
955  | 
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.  | 
956  | 
self.assertEqual({("b",):(("a",),), ("c",):(("b",), ("a",))},  | 
957  | 
index.get_parent_map([("b",), ("c",)]))  | 
|
| 
2158.3.1
by Dmitry Vasiliev
 KnitIndex tests/fixes/optimizations  | 
958  | 
|
959  | 
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  | 
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  | 
| 
2158.3.1
by Dmitry Vasiliev
 KnitIndex tests/fixes/optimizations  | 
964  | 
            ])
 | 
| 
2484.1.1
by John Arbash Meinel
 Add an initial function to read knit indexes in pyrex.  | 
965  | 
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.  | 
966  | 
index.add_records([  | 
967  | 
((utf8_revision_id,), ["option"], ((utf8_revision_id,), 0, 1), [])])  | 
|
968  | 
call = transport.calls.pop(0)  | 
|
969  | 
        # call[1][1] is a StringIO - we can't test it by simple equality.
 | 
|
970  | 
self.assertEqual('put_file_non_atomic', call[0])  | 
|
971  | 
self.assertEqual('filename.kndx', call[1][0])  | 
|
972  | 
        # With no history, _KndxIndex writes a new index:
 | 
|
973  | 
self.assertEqual(_KndxIndex.HEADER +  | 
|
974  | 
"\n%s option 0 1 :" % (utf8_revision_id,),  | 
|
975  | 
call[1][1].getvalue())  | 
|
976  | 
self.assertEqual({'create_parent_dir': True}, call[2])  | 
|
| 
2158.3.1
by Dmitry Vasiliev
 KnitIndex tests/fixes/optimizations  | 
977  | 
|
978  | 
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  | 
979  | 
unicode_revision_id = u"version-\N{CYRILLIC CAPITAL LETTER A}"  | 
980  | 
utf8_revision_id = unicode_revision_id.encode('utf-8')  | 
|
| 
2158.3.1
by Dmitry Vasiliev
 KnitIndex tests/fixes/optimizations  | 
981  | 
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.  | 
982  | 
_KndxIndex.HEADER  | 
983  | 
            ])
 | 
|
984  | 
index = self.get_knit_index(transport, "filename", "r")  | 
|
985  | 
index.add_records([  | 
|
986  | 
(("version",), ["option"], (("version",), 0, 1), [(utf8_revision_id,)])])  | 
|
987  | 
call = transport.calls.pop(0)  | 
|
988  | 
        # call[1][1] is a StringIO - we can't test it by simple equality.
 | 
|
989  | 
self.assertEqual('put_file_non_atomic', call[0])  | 
|
990  | 
self.assertEqual('filename.kndx', call[1][0])  | 
|
991  | 
        # With no history, _KndxIndex writes a new index:
 | 
|
992  | 
self.assertEqual(_KndxIndex.HEADER +  | 
|
993  | 
"\nversion option 0 1 .%s :" % (utf8_revision_id,),  | 
|
994  | 
call[1][1].getvalue())  | 
|
995  | 
self.assertEqual({'create_parent_dir': True}, call[2])  | 
|
996  | 
||
997  | 
def test_keys(self):  | 
|
998  | 
transport = MockTransport([  | 
|
999  | 
_KndxIndex.HEADER  | 
|
1000  | 
            ])
 | 
|
1001  | 
index = self.get_knit_index(transport, "filename", "r")  | 
|
1002  | 
||
1003  | 
self.assertEqual(set(), index.keys())  | 
|
1004  | 
||
1005  | 
index.add_records([(("a",), ["option"], (("a",), 0, 1), [])])  | 
|
1006  | 
self.assertEqual(set([("a",)]), index.keys())  | 
|
1007  | 
||
1008  | 
index.add_records([(("a",), ["option"], (("a",), 0, 1), [])])  | 
|
1009  | 
self.assertEqual(set([("a",)]), index.keys())  | 
|
1010  | 
||
1011  | 
index.add_records([(("b",), ["option"], (("b",), 0, 1), [])])  | 
|
1012  | 
self.assertEqual(set([("a",), ("b",)]), index.keys())  | 
|
1013  | 
||
1014  | 
def add_a_b(self, index, random_id=None):  | 
|
1015  | 
kwargs = {}  | 
|
1016  | 
if random_id is not None:  | 
|
1017  | 
kwargs["random_id"] = random_id  | 
|
1018  | 
index.add_records([  | 
|
1019  | 
(("a",), ["option"], (("a",), 0, 1), [("b",)]),  | 
|
1020  | 
(("a",), ["opt"], (("a",), 1, 2), [("c",)]),  | 
|
1021  | 
(("b",), ["option"], (("b",), 2, 3), [("a",)])  | 
|
1022  | 
], **kwargs)  | 
|
1023  | 
||
1024  | 
def assertIndexIsAB(self, index):  | 
|
1025  | 
self.assertEqual({  | 
|
1026  | 
('a',): (('c',),),  | 
|
1027  | 
('b',): (('a',),),  | 
|
1028  | 
            },
 | 
|
1029  | 
index.get_parent_map(index.keys()))  | 
|
1030  | 
self.assertEqual((("a",), 1, 2), index.get_position(("a",)))  | 
|
1031  | 
self.assertEqual((("b",), 2, 3), index.get_position(("b",)))  | 
|
1032  | 
self.assertEqual(["opt"], index.get_options(("a",)))  | 
|
1033  | 
||
1034  | 
def test_add_versions(self):  | 
|
1035  | 
transport = MockTransport([  | 
|
1036  | 
_KndxIndex.HEADER  | 
|
1037  | 
            ])
 | 
|
1038  | 
index = self.get_knit_index(transport, "filename", "r")  | 
|
1039  | 
||
1040  | 
self.add_a_b(index)  | 
|
1041  | 
call = transport.calls.pop(0)  | 
|
1042  | 
        # call[1][1] is a StringIO - we can't test it by simple equality.
 | 
|
1043  | 
self.assertEqual('put_file_non_atomic', call[0])  | 
|
1044  | 
self.assertEqual('filename.kndx', call[1][0])  | 
|
1045  | 
        # With no history, _KndxIndex writes a new index:
 | 
|
| 
2158.3.1
by Dmitry Vasiliev
 KnitIndex tests/fixes/optimizations  | 
1046  | 
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.  | 
1047  | 
_KndxIndex.HEADER +  | 
| 
2158.3.1
by Dmitry Vasiliev
 KnitIndex tests/fixes/optimizations  | 
1048  | 
"\na option 0 1 .b :"  | 
1049  | 
"\na opt 1 2 .c :"  | 
|
| 
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.  | 
1050  | 
"\nb option 2 3 0 :",  | 
1051  | 
call[1][1].getvalue())  | 
|
1052  | 
self.assertEqual({'create_parent_dir': True}, call[2])  | 
|
1053  | 
self.assertIndexIsAB(index)  | 
|
| 
2158.3.1
by Dmitry Vasiliev
 KnitIndex tests/fixes/optimizations  | 
1054  | 
|
| 
2841.2.1
by Robert Collins
 * Commit no longer checks for new text keys during insertion when the  | 
1055  | 
def test_add_versions_random_id_is_accepted(self):  | 
1056  | 
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.  | 
1057  | 
_KndxIndex.HEADER  | 
| 
2841.2.1
by Robert Collins
 * Commit no longer checks for new text keys during insertion when the  | 
1058  | 
            ])
 | 
1059  | 
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.  | 
1060  | 
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  | 
1061  | 
|
| 
2158.3.1
by Dmitry Vasiliev
 KnitIndex tests/fixes/optimizations  | 
1062  | 
def test_delay_create_and_add_versions(self):  | 
1063  | 
transport = MockTransport()  | 
|
1064  | 
||
| 
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.  | 
1065  | 
index = self.get_knit_index(transport, "filename", "w")  | 
1066  | 
        # dir_mode=0777)
 | 
|
| 
2158.3.1
by Dmitry Vasiliev
 KnitIndex tests/fixes/optimizations  | 
1067  | 
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.  | 
1068  | 
self.add_a_b(index)  | 
1069  | 
        #self.assertEqual(
 | 
|
1070  | 
        #[    {"dir_mode": 0777, "create_parent_dir": True, "mode": "wb"},
 | 
|
1071  | 
        #    kwargs)
 | 
|
1072  | 
        # Two calls: one during which we load the existing index (and when its
 | 
|
1073  | 
        # missing create it), then a second where we write the contents out.
 | 
|
1074  | 
self.assertEqual(2, len(transport.calls))  | 
|
1075  | 
call = transport.calls.pop(0)  | 
|
1076  | 
self.assertEqual('put_file_non_atomic', call[0])  | 
|
1077  | 
self.assertEqual('filename.kndx', call[1][0])  | 
|
1078  | 
        # With no history, _KndxIndex writes a new index:
 | 
|
1079  | 
self.assertEqual(_KndxIndex.HEADER, call[1][1].getvalue())  | 
|
1080  | 
self.assertEqual({'create_parent_dir': True}, call[2])  | 
|
1081  | 
call = transport.calls.pop(0)  | 
|
1082  | 
        # call[1][1] is a StringIO - we can't test it by simple equality.
 | 
|
1083  | 
self.assertEqual('put_file_non_atomic', call[0])  | 
|
1084  | 
self.assertEqual('filename.kndx', call[1][0])  | 
|
1085  | 
        # With no history, _KndxIndex writes a new index:
 | 
|
1086  | 
self.assertEqual(  | 
|
1087  | 
_KndxIndex.HEADER +  | 
|
| 
2158.3.1
by Dmitry Vasiliev
 KnitIndex tests/fixes/optimizations  | 
1088  | 
"\na option 0 1 .b :"  | 
1089  | 
"\na opt 1 2 .c :"  | 
|
1090  | 
"\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.  | 
1091  | 
call[1][1].getvalue())  | 
1092  | 
self.assertEqual({'create_parent_dir': True}, call[2])  | 
|
| 
2158.3.1
by Dmitry Vasiliev
 KnitIndex tests/fixes/optimizations  | 
1093  | 
|
1094  | 
def test_get_position(self):  | 
|
1095  | 
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.  | 
1096  | 
_KndxIndex.HEADER,  | 
| 
2158.3.1
by Dmitry Vasiliev
 KnitIndex tests/fixes/optimizations  | 
1097  | 
"a option 0 1 :",  | 
1098  | 
            "b option 1 2 :"
 | 
|
1099  | 
            ])
 | 
|
| 
2484.1.1
by John Arbash Meinel
 Add an initial function to read knit indexes in pyrex.  | 
1100  | 
index = self.get_knit_index(transport, "filename", "r")  | 
| 
2158.3.1
by Dmitry Vasiliev
 KnitIndex tests/fixes/optimizations  | 
1101  | 
|
| 
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.  | 
1102  | 
self.assertEqual((("a",), 0, 1), index.get_position(("a",)))  | 
1103  | 
self.assertEqual((("b",), 1, 2), index.get_position(("b",)))  | 
|
| 
2158.3.1
by Dmitry Vasiliev
 KnitIndex tests/fixes/optimizations  | 
1104  | 
|
1105  | 
def test_get_method(self):  | 
|
1106  | 
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.  | 
1107  | 
_KndxIndex.HEADER,  | 
| 
2158.3.1
by Dmitry Vasiliev
 KnitIndex tests/fixes/optimizations  | 
1108  | 
"a fulltext,unknown 0 1 :",  | 
1109  | 
"b unknown,line-delta 1 2 :",  | 
|
1110  | 
            "c bad 3 4 :"
 | 
|
1111  | 
            ])
 | 
|
| 
2484.1.1
by John Arbash Meinel
 Add an initial function to read knit indexes in pyrex.  | 
1112  | 
index = self.get_knit_index(transport, "filename", "r")  | 
| 
2158.3.1
by Dmitry Vasiliev
 KnitIndex tests/fixes/optimizations  | 
1113  | 
|
| 
2249.5.12
by John Arbash Meinel
 Change the APIs for VersionedFile, Store, and some of Repository into utf-8  | 
1114  | 
self.assertEqual("fulltext", index.get_method("a"))  | 
1115  | 
self.assertEqual("line-delta", index.get_method("b"))  | 
|
1116  | 
self.assertRaises(errors.KnitIndexUnknownMethod, index.get_method, "c")  | 
|
| 
2158.3.1
by Dmitry Vasiliev
 KnitIndex tests/fixes/optimizations  | 
1117  | 
|
1118  | 
def test_get_options(self):  | 
|
1119  | 
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.  | 
1120  | 
_KndxIndex.HEADER,  | 
| 
2158.3.1
by Dmitry Vasiliev
 KnitIndex tests/fixes/optimizations  | 
1121  | 
"a opt1 0 1 :",  | 
1122  | 
            "b opt2,opt3 1 2 :"
 | 
|
1123  | 
            ])
 | 
|
| 
2484.1.1
by John Arbash Meinel
 Add an initial function to read knit indexes in pyrex.  | 
1124  | 
index = self.get_knit_index(transport, "filename", "r")  | 
| 
2158.3.1
by Dmitry Vasiliev
 KnitIndex tests/fixes/optimizations  | 
1125  | 
|
| 
2249.5.12
by John Arbash Meinel
 Change the APIs for VersionedFile, Store, and some of Repository into utf-8  | 
1126  | 
self.assertEqual(["opt1"], index.get_options("a"))  | 
1127  | 
self.assertEqual(["opt2", "opt3"], index.get_options("b"))  | 
|
| 
2158.3.1
by Dmitry Vasiliev
 KnitIndex tests/fixes/optimizations  | 
1128  | 
|
| 
3287.5.6
by Robert Collins
 Remove _KnitIndex.get_parents.  | 
1129  | 
def test_get_parent_map(self):  | 
| 
2158.3.1
by Dmitry Vasiliev
 KnitIndex tests/fixes/optimizations  | 
1130  | 
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.  | 
1131  | 
_KndxIndex.HEADER,  | 
| 
2158.3.1
by Dmitry Vasiliev
 KnitIndex tests/fixes/optimizations  | 
1132  | 
"a option 0 1 :",  | 
1133  | 
"b option 1 2 0 .c :",  | 
|
1134  | 
            "c option 1 2 1 0 .e :"
 | 
|
1135  | 
            ])
 | 
|
| 
2484.1.1
by John Arbash Meinel
 Add an initial function to read knit indexes in pyrex.  | 
1136  | 
index = self.get_knit_index(transport, "filename", "r")  | 
| 
2158.3.1
by Dmitry Vasiliev
 KnitIndex tests/fixes/optimizations  | 
1137  | 
|
| 
3287.5.6
by Robert Collins
 Remove _KnitIndex.get_parents.  | 
1138  | 
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.  | 
1139  | 
("a",):(),  | 
1140  | 
("b",):(("a",), ("c",)),  | 
|
1141  | 
("c",):(("b",), ("a",), ("e",)),  | 
|
1142  | 
}, index.get_parent_map(index.keys()))  | 
|
| 
2158.3.1
by Dmitry Vasiliev
 KnitIndex tests/fixes/optimizations  | 
1143  | 
|
| 
2484.1.13
by John Arbash Meinel
 Add a test that KnitCorrupt is raised when parent strings are invalid.  | 
1144  | 
def test_impossible_parent(self):  | 
1145  | 
"""Test we get KnitCorrupt if the parent couldn't possibly exist."""  | 
|
1146  | 
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.  | 
1147  | 
_KndxIndex.HEADER,  | 
| 
2484.1.13
by John Arbash Meinel
 Add a test that KnitCorrupt is raised when parent strings are invalid.  | 
1148  | 
"a option 0 1 :",  | 
1149  | 
"b option 0 1 4 :" # We don't have a 4th record  | 
|
1150  | 
            ])
 | 
|
| 
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.  | 
1151  | 
index = self.get_knit_index(transport, 'filename', 'r')  | 
| 
2484.1.17
by John Arbash Meinel
 Workaround for Pyrex <0.9.5 and python >=2.5 incompatibilities.  | 
1152  | 
try:  | 
| 
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.  | 
1153  | 
self.assertRaises(errors.KnitCorrupt, index.keys)  | 
| 
2484.1.17
by John Arbash Meinel
 Workaround for Pyrex <0.9.5 and python >=2.5 incompatibilities.  | 
1154  | 
except TypeError, e:  | 
1155  | 
if (str(e) == ('exceptions must be strings, classes, or instances,'  | 
|
1156  | 
' not exceptions.IndexError')  | 
|
1157  | 
and sys.version_info[0:2] >= (2,5)):  | 
|
1158  | 
self.knownFailure('Pyrex <0.9.5 fails with TypeError when'  | 
|
1159  | 
                                  ' raising new style exceptions with python'
 | 
|
1160  | 
' >=2.5')  | 
|
| 
2484.1.19
by John Arbash Meinel
 Don't suppress the TypeError if it doesn't match our requirements.  | 
1161  | 
else:  | 
1162  | 
                raise
 | 
|
| 
2484.1.13
by John Arbash Meinel
 Add a test that KnitCorrupt is raised when parent strings are invalid.  | 
1163  | 
|
1164  | 
def test_corrupted_parent(self):  | 
|
1165  | 
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.  | 
1166  | 
_KndxIndex.HEADER,  | 
| 
2484.1.13
by John Arbash Meinel
 Add a test that KnitCorrupt is raised when parent strings are invalid.  | 
1167  | 
"a option 0 1 :",  | 
1168  | 
"b option 0 1 :",  | 
|
1169  | 
"c option 0 1 1v :", # Can't have a parent of '1v'  | 
|
1170  | 
            ])
 | 
|
| 
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.  | 
1171  | 
index = self.get_knit_index(transport, 'filename', 'r')  | 
| 
2484.1.17
by John Arbash Meinel
 Workaround for Pyrex <0.9.5 and python >=2.5 incompatibilities.  | 
1172  | 
try:  | 
| 
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.  | 
1173  | 
self.assertRaises(errors.KnitCorrupt, index.keys)  | 
| 
2484.1.17
by John Arbash Meinel
 Workaround for Pyrex <0.9.5 and python >=2.5 incompatibilities.  | 
1174  | 
except TypeError, e:  | 
1175  | 
if (str(e) == ('exceptions must be strings, classes, or instances,'  | 
|
1176  | 
' not exceptions.ValueError')  | 
|
1177  | 
and sys.version_info[0:2] >= (2,5)):  | 
|
1178  | 
self.knownFailure('Pyrex <0.9.5 fails with TypeError when'  | 
|
1179  | 
                                  ' raising new style exceptions with python'
 | 
|
1180  | 
' >=2.5')  | 
|
| 
2484.1.19
by John Arbash Meinel
 Don't suppress the TypeError if it doesn't match our requirements.  | 
1181  | 
else:  | 
1182  | 
                raise
 | 
|
| 
2484.1.13
by John Arbash Meinel
 Add a test that KnitCorrupt is raised when parent strings are invalid.  | 
1183  | 
|
1184  | 
def test_corrupted_parent_in_list(self):  | 
|
1185  | 
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.  | 
1186  | 
_KndxIndex.HEADER,  | 
| 
2484.1.13
by John Arbash Meinel
 Add a test that KnitCorrupt is raised when parent strings are invalid.  | 
1187  | 
"a option 0 1 :",  | 
1188  | 
"b option 0 1 :",  | 
|
| 
2484.1.17
by John Arbash Meinel
 Workaround for Pyrex <0.9.5 and python >=2.5 incompatibilities.  | 
1189  | 
"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.  | 
1190  | 
            ])
 | 
| 
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.  | 
1191  | 
index = self.get_knit_index(transport, 'filename', 'r')  | 
| 
2484.1.17
by John Arbash Meinel
 Workaround for Pyrex <0.9.5 and python >=2.5 incompatibilities.  | 
1192  | 
try:  | 
| 
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.  | 
1193  | 
self.assertRaises(errors.KnitCorrupt, index.keys)  | 
| 
2484.1.17
by John Arbash Meinel
 Workaround for Pyrex <0.9.5 and python >=2.5 incompatibilities.  | 
1194  | 
except TypeError, e:  | 
1195  | 
if (str(e) == ('exceptions must be strings, classes, or instances,'  | 
|
1196  | 
' not exceptions.ValueError')  | 
|
1197  | 
and sys.version_info[0:2] >= (2,5)):  | 
|
1198  | 
self.knownFailure('Pyrex <0.9.5 fails with TypeError when'  | 
|
1199  | 
                                  ' raising new style exceptions with python'
 | 
|
1200  | 
' >=2.5')  | 
|
| 
2484.1.19
by John Arbash Meinel
 Don't suppress the TypeError if it doesn't match our requirements.  | 
1201  | 
else:  | 
1202  | 
                raise
 | 
|
| 
2484.1.13
by John Arbash Meinel
 Add a test that KnitCorrupt is raised when parent strings are invalid.  | 
1203  | 
|
| 
2484.1.18
by John Arbash Meinel
 Test that we properly verify the size and position strings.  | 
1204  | 
def test_invalid_position(self):  | 
1205  | 
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.  | 
1206  | 
_KndxIndex.HEADER,  | 
| 
2484.1.18
by John Arbash Meinel
 Test that we properly verify the size and position strings.  | 
1207  | 
"a option 1v 1 :",  | 
1208  | 
            ])
 | 
|
| 
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.  | 
1209  | 
index = self.get_knit_index(transport, 'filename', 'r')  | 
| 
2484.1.18
by John Arbash Meinel
 Test that we properly verify the size and position strings.  | 
1210  | 
try:  | 
| 
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  | 
self.assertRaises(errors.KnitCorrupt, index.keys)  | 
| 
2484.1.18
by John Arbash Meinel
 Test that we properly verify the size and position strings.  | 
1212  | 
except TypeError, e:  | 
1213  | 
if (str(e) == ('exceptions must be strings, classes, or instances,'  | 
|
1214  | 
' not exceptions.ValueError')  | 
|
1215  | 
and sys.version_info[0:2] >= (2,5)):  | 
|
1216  | 
self.knownFailure('Pyrex <0.9.5 fails with TypeError when'  | 
|
1217  | 
                                  ' raising new style exceptions with python'
 | 
|
1218  | 
' >=2.5')  | 
|
| 
2484.1.19
by John Arbash Meinel
 Don't suppress the TypeError if it doesn't match our requirements.  | 
1219  | 
else:  | 
1220  | 
                raise
 | 
|
| 
2484.1.18
by John Arbash Meinel
 Test that we properly verify the size and position strings.  | 
1221  | 
|
1222  | 
def test_invalid_size(self):  | 
|
1223  | 
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.  | 
1224  | 
_KndxIndex.HEADER,  | 
| 
2484.1.18
by John Arbash Meinel
 Test that we properly verify the size and position strings.  | 
1225  | 
"a option 1 1v :",  | 
1226  | 
            ])
 | 
|
| 
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.  | 
1227  | 
index = self.get_knit_index(transport, 'filename', 'r')  | 
| 
2484.1.18
by John Arbash Meinel
 Test that we properly verify the size and position strings.  | 
1228  | 
try:  | 
| 
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.  | 
1229  | 
self.assertRaises(errors.KnitCorrupt, index.keys)  | 
| 
2484.1.18
by John Arbash Meinel
 Test that we properly verify the size and position strings.  | 
1230  | 
except TypeError, e:  | 
1231  | 
if (str(e) == ('exceptions must be strings, classes, or instances,'  | 
|
1232  | 
' not exceptions.ValueError')  | 
|
1233  | 
and sys.version_info[0:2] >= (2,5)):  | 
|
1234  | 
self.knownFailure('Pyrex <0.9.5 fails with TypeError when'  | 
|
1235  | 
                                  ' raising new style exceptions with python'
 | 
|
1236  | 
' >=2.5')  | 
|
| 
2484.1.19
by John Arbash Meinel
 Don't suppress the TypeError if it doesn't match our requirements.  | 
1237  | 
else:  | 
1238  | 
                raise
 | 
|
| 
2484.1.18
by John Arbash Meinel
 Test that we properly verify the size and position strings.  | 
1239  | 
|
| 
2484.1.24
by John Arbash Meinel
 Add direct tests of how we handle incomplete/'broken' lines  | 
1240  | 
def test_short_line(self):  | 
1241  | 
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.  | 
1242  | 
_KndxIndex.HEADER,  | 
| 
2484.1.24
by John Arbash Meinel
 Add direct tests of how we handle incomplete/'broken' lines  | 
1243  | 
"a option 0 10 :",  | 
1244  | 
"b option 10 10 0", # This line isn't terminated, ignored  | 
|
1245  | 
            ])
 | 
|
1246  | 
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.  | 
1247  | 
self.assertEqual(set([('a',)]), index.keys())  | 
| 
2484.1.24
by John Arbash Meinel
 Add direct tests of how we handle incomplete/'broken' lines  | 
1248  | 
|
1249  | 
def test_skip_incomplete_record(self):  | 
|
1250  | 
        # A line with bogus data should just be skipped
 | 
|
1251  | 
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.  | 
1252  | 
_KndxIndex.HEADER,  | 
| 
2484.1.24
by John Arbash Meinel
 Add direct tests of how we handle incomplete/'broken' lines  | 
1253  | 
"a option 0 10 :",  | 
1254  | 
"b option 10 10 0", # This line isn't terminated, ignored  | 
|
1255  | 
"c option 20 10 0 :", # Properly terminated, and starts with '\n'  | 
|
1256  | 
            ])
 | 
|
1257  | 
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.  | 
1258  | 
self.assertEqual(set([('a',), ('c',)]), index.keys())  | 
| 
2484.1.24
by John Arbash Meinel
 Add direct tests of how we handle incomplete/'broken' lines  | 
1259  | 
|
1260  | 
def test_trailing_characters(self):  | 
|
1261  | 
        # A line with bogus data should just be skipped
 | 
|
1262  | 
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.  | 
1263  | 
_KndxIndex.HEADER,  | 
| 
2484.1.24
by John Arbash Meinel
 Add direct tests of how we handle incomplete/'broken' lines  | 
1264  | 
"a option 0 10 :",  | 
1265  | 
"b option 10 10 0 :a", # This line has extra trailing characters  | 
|
1266  | 
"c option 20 10 0 :", # Properly terminated, and starts with '\n'  | 
|
1267  | 
            ])
 | 
|
1268  | 
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.  | 
1269  | 
self.assertEqual(set([('a',), ('c',)]), index.keys())  | 
| 
2484.1.24
by John Arbash Meinel
 Add direct tests of how we handle incomplete/'broken' lines  | 
1270  | 
|
| 
2158.3.1
by Dmitry Vasiliev
 KnitIndex tests/fixes/optimizations  | 
1271  | 
|
| 
2484.1.1
by John Arbash Meinel
 Add an initial function to read knit indexes in pyrex.  | 
1272  | 
class LowLevelKnitIndexTests_c(LowLevelKnitIndexTests):  | 
1273  | 
||
1274  | 
_test_needs_features = [CompiledKnitFeature]  | 
|
1275  | 
||
| 
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.  | 
1276  | 
def get_knit_index(self, transport, name, mode):  | 
1277  | 
mapper = ConstantMapper(name)  | 
|
| 
2484.1.1
by John Arbash Meinel
 Add an initial function to read knit indexes in pyrex.  | 
1278  | 
orig = knit._load_data  | 
1279  | 
def reset():  | 
|
1280  | 
knit._load_data = orig  | 
|
1281  | 
self.addCleanup(reset)  | 
|
| 
2484.1.12
by John Arbash Meinel
 Switch the layout to use a matching _knit_load_data_py.py and _knit_load_data_c.pyx  | 
1282  | 
from bzrlib._knit_load_data_c import _load_data_c  | 
1283  | 
knit._load_data = _load_data_c  | 
|
| 
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.  | 
1284  | 
allow_writes = lambda: mode == 'w'  | 
1285  | 
return _KndxIndex(transport, mapper, lambda:None, allow_writes, lambda:True)  | 
|
| 
2484.1.1
by John Arbash Meinel
 Add an initial function to read knit indexes in pyrex.  | 
1286  | 
|
1287  | 
||
| 
1684.3.3
by Robert Collins
 Add a special cased weaves to knit converter.  | 
1288  | 
class KnitTests(TestCaseWithTransport):  | 
1289  | 
"""Class containing knit test helper routines."""  | 
|
| 
1563.2.16
by Robert Collins
 Change WeaveStore into VersionedFileStore and make its versoined file class parameterisable.  | 
1290  | 
|
| 
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.  | 
1291  | 
def make_test_knit(self, annotate=False, name='test'):  | 
1292  | 
mapper = ConstantMapper(name)  | 
|
1293  | 
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  | 
1294  | 
|
1295  | 
||
| 
3787.1.1
by Robert Collins
 Embed the failed text in sha1 knit errors.  | 
1296  | 
class TestBadShaError(KnitTests):  | 
1297  | 
"""Tests for handling of sha errors."""  | 
|
1298  | 
||
1299  | 
def test_exception_has_text(self):  | 
|
1300  | 
        # having the failed text included in the error allows for recovery.
 | 
|
1301  | 
source = self.make_test_knit()  | 
|
1302  | 
target = self.make_test_knit(name="target")  | 
|
1303  | 
if not source._max_delta_chain:  | 
|
1304  | 
raise TestNotApplicable(  | 
|
1305  | 
"cannot get delta-caused sha failures without deltas.")  | 
|
1306  | 
        # create a basis
 | 
|
1307  | 
basis = ('basis',)  | 
|
1308  | 
broken = ('broken',)  | 
|
1309  | 
source.add_lines(basis, (), ['foo\n'])  | 
|
1310  | 
source.add_lines(broken, (basis,), ['foo\n', 'bar\n'])  | 
|
1311  | 
        # Seed target with a bad basis text
 | 
|
1312  | 
target.add_lines(basis, (), ['gam\n'])  | 
|
1313  | 
target.insert_record_stream(  | 
|
1314  | 
source.get_record_stream([broken], 'unordered', False))  | 
|
1315  | 
err = self.assertRaises(errors.KnitCorrupt,  | 
|
1316  | 
target.get_record_stream([broken], 'unordered', True).next)  | 
|
1317  | 
self.assertEqual(['gam\n', 'bar\n'], err.content)  | 
|
| 
3787.1.2
by Robert Collins
 Ensure SHA1KnitCorrupt formats ok.  | 
1318  | 
        # Test for formatting with live data
 | 
1319  | 
self.assertStartsWith(str(err), "Knit ")  | 
|
| 
3787.1.1
by Robert Collins
 Embed the failed text in sha1 knit errors.  | 
1320  | 
|
1321  | 
||
| 
2102.2.1
by John Arbash Meinel
 Fix bug #64789 _KnitIndex.add_versions() should dict compress new revisions  | 
1322  | 
class TestKnitIndex(KnitTests):  | 
1323  | 
||
1324  | 
def test_add_versions_dictionary_compresses(self):  | 
|
1325  | 
"""Adding versions to the index should update the lookup dict"""  | 
|
1326  | 
knit = self.make_test_knit()  | 
|
1327  | 
idx = knit._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.  | 
1328  | 
idx.add_records([(('a-1',), ['fulltext'], (('a-1',), 0, 0), [])])  | 
| 
2102.2.1
by John Arbash Meinel
 Fix bug #64789 _KnitIndex.add_versions() should dict compress new revisions  | 
1329  | 
self.check_file_contents('test.kndx',  | 
1330  | 
'# bzr knit index 8\n'  | 
|
1331  | 
'\n'  | 
|
1332  | 
            'a-1 fulltext 0 0  :'
 | 
|
1333  | 
            )
 | 
|
| 
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.  | 
1334  | 
idx.add_records([  | 
1335  | 
(('a-2',), ['fulltext'], (('a-2',), 0, 0), [('a-1',)]),  | 
|
1336  | 
(('a-3',), ['fulltext'], (('a-3',), 0, 0), [('a-2',)]),  | 
|
1337  | 
            ])
 | 
|
| 
2102.2.1
by John Arbash Meinel
 Fix bug #64789 _KnitIndex.add_versions() should dict compress new revisions  | 
1338  | 
self.check_file_contents('test.kndx',  | 
1339  | 
'# bzr knit index 8\n'  | 
|
1340  | 
'\n'  | 
|
1341  | 
'a-1 fulltext 0 0 :\n'  | 
|
1342  | 
'a-2 fulltext 0 0 0 :\n'  | 
|
1343  | 
            'a-3 fulltext 0 0 1 :'
 | 
|
1344  | 
            )
 | 
|
| 
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.  | 
1345  | 
self.assertEqual(set([('a-3',), ('a-1',), ('a-2',)]), idx.keys())  | 
1346  | 
self.assertEqual({  | 
|
1347  | 
('a-1',): ((('a-1',), 0, 0), None, (), ('fulltext', False)),  | 
|
1348  | 
('a-2',): ((('a-2',), 0, 0), None, (('a-1',),), ('fulltext', False)),  | 
|
1349  | 
('a-3',): ((('a-3',), 0, 0), None, (('a-2',),), ('fulltext', False)),  | 
|
1350  | 
}, idx.get_build_details(idx.keys()))  | 
|
1351  | 
self.assertEqual({('a-1',):(),  | 
|
1352  | 
('a-2',):(('a-1',),),  | 
|
1353  | 
('a-3',):(('a-2',),),},  | 
|
1354  | 
idx.get_parent_map(idx.keys()))  | 
|
| 
2102.2.1
by John Arbash Meinel
 Fix bug #64789 _KnitIndex.add_versions() should dict compress new revisions  | 
1355  | 
|
1356  | 
def test_add_versions_fails_clean(self):  | 
|
1357  | 
"""If add_versions fails in the middle, it restores a pristine state.  | 
|
1358  | 
||
1359  | 
        Any modifications that are made to the index are reset if all versions
 | 
|
1360  | 
        cannot be added.
 | 
|
1361  | 
        """
 | 
|
1362  | 
        # This cheats a little bit by passing in a generator which will
 | 
|
1363  | 
        # raise an exception before the processing finishes
 | 
|
1364  | 
        # Other possibilities would be to have an version with the wrong number
 | 
|
1365  | 
        # of entries, or to make the backing transport unable to write any
 | 
|
1366  | 
        # files.
 | 
|
1367  | 
||
1368  | 
knit = self.make_test_knit()  | 
|
1369  | 
idx = knit._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.  | 
1370  | 
idx.add_records([(('a-1',), ['fulltext'], (('a-1',), 0, 0), [])])  | 
| 
2102.2.1
by John Arbash Meinel
 Fix bug #64789 _KnitIndex.add_versions() should dict compress new revisions  | 
1371  | 
|
1372  | 
class StopEarly(Exception):  | 
|
1373  | 
            pass
 | 
|
1374  | 
||
1375  | 
def generate_failure():  | 
|
1376  | 
"""Add some entries and then raise an exception"""  | 
|
| 
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.  | 
1377  | 
yield (('a-2',), ['fulltext'], (None, 0, 0), ('a-1',))  | 
1378  | 
yield (('a-3',), ['fulltext'], (None, 0, 0), ('a-2',))  | 
|
| 
2102.2.1
by John Arbash Meinel
 Fix bug #64789 _KnitIndex.add_versions() should dict compress new revisions  | 
1379  | 
raise StopEarly()  | 
1380  | 
||
1381  | 
        # 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.  | 
1382  | 
def assertA1Only():  | 
1383  | 
self.assertEqual(set([('a-1',)]), set(idx.keys()))  | 
|
1384  | 
self.assertEqual(  | 
|
1385  | 
{('a-1',): ((('a-1',), 0, 0), None, (), ('fulltext', False))},  | 
|
1386  | 
idx.get_build_details([('a-1',)]))  | 
|
1387  | 
self.assertEqual({('a-1',):()}, idx.get_parent_map(idx.keys()))  | 
|
1388  | 
||
1389  | 
assertA1Only()  | 
|
1390  | 
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  | 
1391  | 
        # 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.  | 
1392  | 
assertA1Only()  | 
| 
2171.1.1
by John Arbash Meinel
 Knit index files should ignore empty indexes rather than consider them corrupt.  | 
1393  | 
|
1394  | 
def test_knit_index_ignores_empty_files(self):  | 
|
1395  | 
        # There was a race condition in older bzr, where a ^C at the right time
 | 
|
1396  | 
        # could leave an empty .kndx file, which bzr would later claim was a
 | 
|
1397  | 
        # corrupted file since the header was not present. In reality, the file
 | 
|
1398  | 
        # just wasn't created, so it should be ignored.
 | 
|
1399  | 
t = get_transport('.')  | 
|
1400  | 
t.put_bytes('test.kndx', '')  | 
|
1401  | 
||
1402  | 
knit = self.make_test_knit()  | 
|
1403  | 
||
1404  | 
def test_knit_index_checks_header(self):  | 
|
1405  | 
t = get_transport('.')  | 
|
1406  | 
t.put_bytes('test.kndx', '# 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.  | 
1407  | 
k = self.make_test_knit()  | 
1408  | 
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.  | 
1409  | 
|
1410  | 
||
1411  | 
class TestGraphIndexKnit(KnitTests):  | 
|
1412  | 
"""Tests for knits using a GraphIndex rather than a KnitIndex."""  | 
|
1413  | 
||
1414  | 
def make_g_index(self, name, ref_lists=0, nodes=[]):  | 
|
1415  | 
builder = GraphIndexBuilder(ref_lists)  | 
|
1416  | 
for node, references, value in nodes:  | 
|
1417  | 
builder.add_node(node, references, value)  | 
|
1418  | 
stream = builder.finish()  | 
|
1419  | 
trans = self.get_transport()  | 
|
| 
2890.2.1
by Robert Collins
 * ``bzrlib.index.GraphIndex`` now requires a size parameter to the  | 
1420  | 
size = trans.put_file(name, stream)  | 
1421  | 
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.  | 
1422  | 
|
| 
2592.3.19
by Robert Collins
 Change KnitGraphIndex from returning data to performing a callback on insertions.  | 
1423  | 
def two_graph_index(self, deltas=False, catch_adds=False):  | 
| 
2592.3.13
by Robert Collins
 Implement KnitGraphIndex.get_method.  | 
1424  | 
"""Build a two-graph index.  | 
1425  | 
||
1426  | 
        :param deltas: If true, use underlying indices with two node-ref
 | 
|
1427  | 
            lists and 'parent' set to a delta-compressed against tail.
 | 
|
1428  | 
        """
 | 
|
| 
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.  | 
1429  | 
        # build a complex graph across several indices.
 | 
| 
2592.3.13
by Robert Collins
 Implement KnitGraphIndex.get_method.  | 
1430  | 
if deltas:  | 
| 
2624.2.5
by Robert Collins
 Change bzrlib.index.Index keys to be 1-tuples, not strings.  | 
1431  | 
            # delta compression inn the index
 | 
| 
2592.3.13
by Robert Collins
 Implement KnitGraphIndex.get_method.  | 
1432  | 
index1 = self.make_g_index('1', 2, [  | 
| 
2624.2.5
by Robert Collins
 Change bzrlib.index.Index keys to be 1-tuples, not strings.  | 
1433  | 
(('tip', ), 'N0 100', ([('parent', )], [], )),  | 
1434  | 
(('tail', ), '', ([], []))])  | 
|
| 
2592.3.13
by Robert Collins
 Implement KnitGraphIndex.get_method.  | 
1435  | 
index2 = self.make_g_index('2', 2, [  | 
| 
2624.2.5
by Robert Collins
 Change bzrlib.index.Index keys to be 1-tuples, not strings.  | 
1436  | 
(('parent', ), ' 100 78', ([('tail', ), ('ghost', )], [('tail', )])),  | 
1437  | 
(('separate', ), '', ([], []))])  | 
|
| 
2592.3.13
by Robert Collins
 Implement KnitGraphIndex.get_method.  | 
1438  | 
else:  | 
| 
2624.2.5
by Robert Collins
 Change bzrlib.index.Index keys to be 1-tuples, not strings.  | 
1439  | 
            # just blob location and graph in the index.
 | 
| 
2592.3.13
by Robert Collins
 Implement KnitGraphIndex.get_method.  | 
1440  | 
index1 = self.make_g_index('1', 1, [  | 
| 
2624.2.5
by Robert Collins
 Change bzrlib.index.Index keys to be 1-tuples, not strings.  | 
1441  | 
(('tip', ), 'N0 100', ([('parent', )], )),  | 
1442  | 
(('tail', ), '', ([], ))])  | 
|
| 
2592.3.13
by Robert Collins
 Implement KnitGraphIndex.get_method.  | 
1443  | 
index2 = self.make_g_index('2', 1, [  | 
| 
2624.2.5
by Robert Collins
 Change bzrlib.index.Index keys to be 1-tuples, not strings.  | 
1444  | 
(('parent', ), ' 100 78', ([('tail', ), ('ghost', )], )),  | 
1445  | 
(('separate', ), '', ([], ))])  | 
|
| 
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.  | 
1446  | 
combined_index = CombinedGraphIndex([index1, index2])  | 
| 
2592.3.19
by Robert Collins
 Change KnitGraphIndex from returning data to performing a callback on insertions.  | 
1447  | 
if catch_adds:  | 
1448  | 
self.combined_index = combined_index  | 
|
1449  | 
self.caught_entries = []  | 
|
1450  | 
add_callback = self.catch_add  | 
|
1451  | 
else:  | 
|
1452  | 
add_callback = None  | 
|
| 
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.  | 
1453  | 
return _KnitGraphIndex(combined_index, lambda:True, deltas=deltas,  | 
| 
2592.3.19
by Robert Collins
 Change KnitGraphIndex from returning data to performing a callback on insertions.  | 
1454  | 
add_callback=add_callback)  | 
| 
2592.3.4
by Robert Collins
 Implement get_ancestry/get_ancestry_with_ghosts for KnitGraphIndex.  | 
1455  | 
|
| 
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.  | 
1456  | 
def test_keys(self):  | 
1457  | 
index = self.two_graph_index()  | 
|
1458  | 
self.assertEqual(set([('tail',), ('tip',), ('parent',), ('separate',)]),  | 
|
1459  | 
set(index.keys()))  | 
|
| 
2592.3.9
by Robert Collins
 Implement KnitGraphIndex.has_version.  | 
1460  | 
|
| 
2592.3.10
by Robert Collins
 Implement KnitGraphIndex.get_position.  | 
1461  | 
def test_get_position(self):  | 
1462  | 
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.  | 
1463  | 
self.assertEqual((index._graph_index._indices[0], 0, 100), index.get_position(('tip',)))  | 
1464  | 
self.assertEqual((index._graph_index._indices[1], 100, 78), index.get_position(('parent',)))  | 
|
| 
2592.3.10
by Robert Collins
 Implement KnitGraphIndex.get_position.  | 
1465  | 
|
| 
2592.3.13
by Robert Collins
 Implement KnitGraphIndex.get_method.  | 
1466  | 
def test_get_method_deltas(self):  | 
1467  | 
index = self.two_graph_index(deltas=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.  | 
1468  | 
self.assertEqual('fulltext', index.get_method(('tip',)))  | 
1469  | 
self.assertEqual('line-delta', index.get_method(('parent',)))  | 
|
| 
2592.3.11
by Robert Collins
 Implement KnitGraphIndex.get_method.  | 
1470  | 
|
| 
2592.3.13
by Robert Collins
 Implement KnitGraphIndex.get_method.  | 
1471  | 
def test_get_method_no_deltas(self):  | 
1472  | 
        # check that the parent-history lookup is ignored with deltas=False.
 | 
|
1473  | 
index = self.two_graph_index(deltas=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.  | 
1474  | 
self.assertEqual('fulltext', index.get_method(('tip',)))  | 
1475  | 
self.assertEqual('fulltext', index.get_method(('parent',)))  | 
|
| 
2592.3.13
by Robert Collins
 Implement KnitGraphIndex.get_method.  | 
1476  | 
|
| 
2592.3.14
by Robert Collins
 Implement KnitGraphIndex.get_options.  | 
1477  | 
def test_get_options_deltas(self):  | 
1478  | 
index = self.two_graph_index(deltas=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.  | 
1479  | 
self.assertEqual(['fulltext', 'no-eol'], index.get_options(('tip',)))  | 
1480  | 
self.assertEqual(['line-delta'], index.get_options(('parent',)))  | 
|
| 
2592.3.14
by Robert Collins
 Implement KnitGraphIndex.get_options.  | 
1481  | 
|
1482  | 
def test_get_options_no_deltas(self):  | 
|
1483  | 
        # check that the parent-history lookup is ignored with deltas=False.
 | 
|
1484  | 
index = self.two_graph_index(deltas=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.  | 
1485  | 
self.assertEqual(['fulltext', 'no-eol'], index.get_options(('tip',)))  | 
1486  | 
self.assertEqual(['fulltext'], index.get_options(('parent',)))  | 
|
1487  | 
||
1488  | 
def test_get_parent_map(self):  | 
|
1489  | 
index = self.two_graph_index()  | 
|
1490  | 
self.assertEqual({('parent',):(('tail',), ('ghost',))},  | 
|
1491  | 
index.get_parent_map([('parent',), ('ghost',)]))  | 
|
| 
2592.3.14
by Robert Collins
 Implement KnitGraphIndex.get_options.  | 
1492  | 
|
| 
2592.3.19
by Robert Collins
 Change KnitGraphIndex from returning data to performing a callback on insertions.  | 
1493  | 
def catch_add(self, entries):  | 
1494  | 
self.caught_entries.append(entries)  | 
|
1495  | 
||
1496  | 
def test_add_no_callback_errors(self):  | 
|
1497  | 
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.  | 
1498  | 
self.assertRaises(errors.ReadOnlyError, index.add_records,  | 
1499  | 
[(('new',), 'fulltext,no-eol', (None, 50, 60), ['separate'])])  | 
|
| 
2592.3.19
by Robert Collins
 Change KnitGraphIndex from returning data to performing a callback on insertions.  | 
1500  | 
|
| 
2592.3.17
by Robert Collins
 Add add_version(s) to KnitGraphIndex, completing the required api for KnitVersionedFile.  | 
1501  | 
def test_add_version_smoke(self):  | 
| 
2592.3.19
by Robert Collins
 Change KnitGraphIndex from returning data to performing a callback on insertions.  | 
1502  | 
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.  | 
1503  | 
index.add_records([(('new',), 'fulltext,no-eol', (None, 50, 60),  | 
1504  | 
[('separate',)])])  | 
|
| 
2624.2.5
by Robert Collins
 Change bzrlib.index.Index keys to be 1-tuples, not strings.  | 
1505  | 
self.assertEqual([[(('new', ), 'N50 60', ((('separate',),),))]],  | 
| 
2592.3.19
by Robert Collins
 Change KnitGraphIndex from returning data to performing a callback on insertions.  | 
1506  | 
self.caught_entries)  | 
| 
2592.3.17
by Robert Collins
 Add add_version(s) to KnitGraphIndex, completing the required api for KnitVersionedFile.  | 
1507  | 
|
1508  | 
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.  | 
1509  | 
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.  | 
1510  | 
self.assertRaises(errors.KnitCorrupt, index.add_records,  | 
1511  | 
[(('new',), 'no-eol,line-delta', (None, 0, 100), [('parent',)])])  | 
|
| 
2592.3.19
by Robert Collins
 Change KnitGraphIndex from returning data to performing a callback on insertions.  | 
1512  | 
self.assertEqual([], self.caught_entries)  | 
| 
2592.3.17
by Robert Collins
 Add add_version(s) to KnitGraphIndex, completing the required api for KnitVersionedFile.  | 
1513  | 
|
1514  | 
def test_add_version_same_dup(self):  | 
|
| 
2592.3.19
by Robert Collins
 Change KnitGraphIndex from returning data to performing a callback on insertions.  | 
1515  | 
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.  | 
1516  | 
        # options can be spelt two different ways
 | 
| 
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.  | 
1517  | 
index.add_records([(('tip',), 'fulltext,no-eol', (None, 0, 100), [('parent',)])])  | 
1518  | 
index.add_records([(('tip',), 'no-eol,fulltext', (None, 0, 100), [('parent',)])])  | 
|
1519  | 
        # position/length are ignored (because each pack could have fulltext or
 | 
|
1520  | 
        # delta, and be at a different position.
 | 
|
1521  | 
index.add_records([(('tip',), 'fulltext,no-eol', (None, 50, 100),  | 
|
1522  | 
[('parent',)])])  | 
|
1523  | 
index.add_records([(('tip',), 'fulltext,no-eol', (None, 0, 1000),  | 
|
1524  | 
[('parent',)])])  | 
|
1525  | 
        # but neither should have added data:
 | 
|
1526  | 
self.assertEqual([[], [], [], []], self.caught_entries)  | 
|
| 
2592.3.17
by Robert Collins
 Add add_version(s) to KnitGraphIndex, completing the required api for KnitVersionedFile.  | 
1527  | 
|
1528  | 
def test_add_version_different_dup(self):  | 
|
| 
2592.3.19
by Robert Collins
 Change KnitGraphIndex from returning data to performing a callback on insertions.  | 
1529  | 
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.  | 
1530  | 
        # change options
 | 
| 
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.  | 
1531  | 
self.assertRaises(errors.KnitCorrupt, index.add_records,  | 
1532  | 
[(('tip',), 'no-eol,line-delta', (None, 0, 100), [('parent',)])])  | 
|
1533  | 
self.assertRaises(errors.KnitCorrupt, index.add_records,  | 
|
1534  | 
[(('tip',), 'line-delta,no-eol', (None, 0, 100), [('parent',)])])  | 
|
1535  | 
self.assertRaises(errors.KnitCorrupt, index.add_records,  | 
|
1536  | 
[(('tip',), 'fulltext', (None, 0, 100), [('parent',)])])  | 
|
| 
2592.3.17
by Robert Collins
 Add add_version(s) to KnitGraphIndex, completing the required api for KnitVersionedFile.  | 
1537  | 
        # parents
 | 
| 
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.  | 
1538  | 
self.assertRaises(errors.KnitCorrupt, index.add_records,  | 
1539  | 
[(('tip',), 'fulltext,no-eol', (None, 0, 100), [])])  | 
|
| 
2592.3.19
by Robert Collins
 Change KnitGraphIndex from returning data to performing a callback on insertions.  | 
1540  | 
self.assertEqual([], self.caught_entries)  | 
| 
2592.3.17
by Robert Collins
 Add add_version(s) to KnitGraphIndex, completing the required api for KnitVersionedFile.  | 
1541  | 
|
1542  | 
def test_add_versions_nodeltas(self):  | 
|
| 
2592.3.19
by Robert Collins
 Change KnitGraphIndex from returning data to performing a callback on insertions.  | 
1543  | 
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.  | 
1544  | 
index.add_records([  | 
1545  | 
(('new',), 'fulltext,no-eol', (None, 50, 60), [('separate',)]),  | 
|
1546  | 
(('new2',), 'fulltext', (None, 0, 6), [('new',)]),  | 
|
| 
2592.3.19
by Robert Collins
 Change KnitGraphIndex from returning data to performing a callback on insertions.  | 
1547  | 
                ])
 | 
| 
2624.2.5
by Robert Collins
 Change bzrlib.index.Index keys to be 1-tuples, not strings.  | 
1548  | 
self.assertEqual([(('new', ), 'N50 60', ((('separate',),),)),  | 
1549  | 
(('new2', ), ' 0 6', ((('new',),),))],  | 
|
| 
2592.3.19
by Robert Collins
 Change KnitGraphIndex from returning data to performing a callback on insertions.  | 
1550  | 
sorted(self.caught_entries[0]))  | 
1551  | 
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.  | 
1552  | 
|
1553  | 
def test_add_versions_deltas(self):  | 
|
| 
2592.3.19
by Robert Collins
 Change KnitGraphIndex from returning data to performing a callback on insertions.  | 
1554  | 
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.  | 
1555  | 
index.add_records([  | 
1556  | 
(('new',), 'fulltext,no-eol', (None, 50, 60), [('separate',)]),  | 
|
1557  | 
(('new2',), 'line-delta', (None, 0, 6), [('new',)]),  | 
|
| 
2592.3.19
by Robert Collins
 Change KnitGraphIndex from returning data to performing a callback on insertions.  | 
1558  | 
                ])
 | 
| 
2624.2.5
by Robert Collins
 Change bzrlib.index.Index keys to be 1-tuples, not strings.  | 
1559  | 
self.assertEqual([(('new', ), 'N50 60', ((('separate',),), ())),  | 
1560  | 
(('new2', ), ' 0 6', ((('new',),), (('new',),), ))],  | 
|
| 
2592.3.19
by Robert Collins
 Change KnitGraphIndex from returning data to performing a callback on insertions.  | 
1561  | 
sorted(self.caught_entries[0]))  | 
1562  | 
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.  | 
1563  | 
|
1564  | 
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.  | 
1565  | 
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.  | 
1566  | 
self.assertRaises(errors.KnitCorrupt, index.add_records,  | 
1567  | 
[(('new',), 'no-eol,line-delta', (None, 0, 100), [('parent',)])])  | 
|
| 
2592.3.19
by Robert Collins
 Change KnitGraphIndex from returning data to performing a callback on insertions.  | 
1568  | 
self.assertEqual([], self.caught_entries)  | 
| 
2592.3.17
by Robert Collins
 Add add_version(s) to KnitGraphIndex, completing the required api for KnitVersionedFile.  | 
1569  | 
|
| 
2841.2.1
by Robert Collins
 * Commit no longer checks for new text keys during insertion when the  | 
1570  | 
def test_add_versions_random_id_accepted(self):  | 
1571  | 
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.  | 
1572  | 
index.add_records([], random_id=True)  | 
| 
2841.2.1
by Robert Collins
 * Commit no longer checks for new text keys during insertion when the  | 
1573  | 
|
| 
2592.3.17
by Robert Collins
 Add add_version(s) to KnitGraphIndex, completing the required api for KnitVersionedFile.  | 
1574  | 
def test_add_versions_same_dup(self):  | 
| 
2592.3.19
by Robert Collins
 Change KnitGraphIndex from returning data to performing a callback on insertions.  | 
1575  | 
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.  | 
1576  | 
        # options can be spelt two different ways
 | 
| 
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.  | 
1577  | 
index.add_records([(('tip',), 'fulltext,no-eol', (None, 0, 100),  | 
1578  | 
[('parent',)])])  | 
|
1579  | 
index.add_records([(('tip',), 'no-eol,fulltext', (None, 0, 100),  | 
|
1580  | 
[('parent',)])])  | 
|
1581  | 
        # position/length are ignored (because each pack could have fulltext or
 | 
|
1582  | 
        # delta, and be at a different position.
 | 
|
1583  | 
index.add_records([(('tip',), 'fulltext,no-eol', (None, 50, 100),  | 
|
1584  | 
[('parent',)])])  | 
|
1585  | 
index.add_records([(('tip',), 'fulltext,no-eol', (None, 0, 1000),  | 
|
1586  | 
[('parent',)])])  | 
|
| 
2592.3.19
by Robert Collins
 Change KnitGraphIndex from returning data to performing a callback on insertions.  | 
1587  | 
        # 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.  | 
1588  | 
self.assertEqual([[], [], [], []], self.caught_entries)  | 
| 
2592.3.17
by Robert Collins
 Add add_version(s) to KnitGraphIndex, completing the required api for KnitVersionedFile.  | 
1589  | 
|
1590  | 
def test_add_versions_different_dup(self):  | 
|
| 
2592.3.19
by Robert Collins
 Change KnitGraphIndex from returning data to performing a callback on insertions.  | 
1591  | 
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.  | 
1592  | 
        # change options
 | 
| 
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.  | 
1593  | 
self.assertRaises(errors.KnitCorrupt, index.add_records,  | 
1594  | 
[(('tip',), 'no-eol,line-delta', (None, 0, 100), [('parent',)])])  | 
|
1595  | 
self.assertRaises(errors.KnitCorrupt, index.add_records,  | 
|
1596  | 
[(('tip',), 'line-delta,no-eol', (None, 0, 100), [('parent',)])])  | 
|
1597  | 
self.assertRaises(errors.KnitCorrupt, index.add_records,  | 
|
1598  | 
[(('tip',), 'fulltext', (None, 0, 100), [('parent',)])])  | 
|
| 
2592.3.17
by Robert Collins
 Add add_version(s) to KnitGraphIndex, completing the required api for KnitVersionedFile.  | 
1599  | 
        # parents
 | 
| 
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  | 
self.assertRaises(errors.KnitCorrupt, index.add_records,  | 
1601  | 
[(('tip',), 'fulltext,no-eol', (None, 0, 100), [])])  | 
|
| 
2592.3.17
by Robert Collins
 Add add_version(s) to KnitGraphIndex, completing the required api for KnitVersionedFile.  | 
1602  | 
        # change options in the second record
 | 
| 
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.  | 
1603  | 
self.assertRaises(errors.KnitCorrupt, index.add_records,  | 
1604  | 
[(('tip',), 'fulltext,no-eol', (None, 0, 100), [('parent',)]),  | 
|
1605  | 
(('tip',), 'no-eol,line-delta', (None, 0, 100), [('parent',)])])  | 
|
| 
2592.3.19
by Robert Collins
 Change KnitGraphIndex from returning data to performing a callback on insertions.  | 
1606  | 
self.assertEqual([], self.caught_entries)  | 
| 
2592.3.34
by Robert Collins
 Rough unfactored support for parentless KnitGraphIndexs.  | 
1607  | 
|
| 
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.  | 
1608  | 
|
| 
2592.3.34
by Robert Collins
 Rough unfactored support for parentless KnitGraphIndexs.  | 
1609  | 
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.  | 
1610  | 
"""Tests for knits using _KnitGraphIndex with no parents."""  | 
| 
2592.3.34
by Robert Collins
 Rough unfactored support for parentless KnitGraphIndexs.  | 
1611  | 
|
1612  | 
def make_g_index(self, name, ref_lists=0, nodes=[]):  | 
|
1613  | 
builder = GraphIndexBuilder(ref_lists)  | 
|
1614  | 
for node, references in nodes:  | 
|
1615  | 
builder.add_node(node, references)  | 
|
1616  | 
stream = builder.finish()  | 
|
1617  | 
trans = self.get_transport()  | 
|
| 
2890.2.1
by Robert Collins
 * ``bzrlib.index.GraphIndex`` now requires a size parameter to the  | 
1618  | 
size = trans.put_file(name, stream)  | 
1619  | 
return GraphIndex(trans, name, size)  | 
|
| 
2592.3.34
by Robert Collins
 Rough unfactored support for parentless KnitGraphIndexs.  | 
1620  | 
|
1621  | 
def test_parents_deltas_incompatible(self):  | 
|
1622  | 
index = CombinedGraphIndex([])  | 
|
| 
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.  | 
1623  | 
self.assertRaises(errors.KnitError, _KnitGraphIndex, lambda:True,  | 
1624  | 
index, deltas=True, parents=False)  | 
|
| 
2592.3.34
by Robert Collins
 Rough unfactored support for parentless KnitGraphIndexs.  | 
1625  | 
|
1626  | 
def two_graph_index(self, catch_adds=False):  | 
|
1627  | 
"""Build a two-graph index.  | 
|
1628  | 
||
1629  | 
        :param deltas: If true, use underlying indices with two node-ref
 | 
|
1630  | 
            lists and 'parent' set to a delta-compressed against tail.
 | 
|
1631  | 
        """
 | 
|
1632  | 
        # put several versions in the index.
 | 
|
1633  | 
index1 = self.make_g_index('1', 0, [  | 
|
| 
2624.2.5
by Robert Collins
 Change bzrlib.index.Index keys to be 1-tuples, not strings.  | 
1634  | 
(('tip', ), 'N0 100'),  | 
1635  | 
(('tail', ), '')])  | 
|
| 
2592.3.34
by Robert Collins
 Rough unfactored support for parentless KnitGraphIndexs.  | 
1636  | 
index2 = self.make_g_index('2', 0, [  | 
| 
2624.2.5
by Robert Collins
 Change bzrlib.index.Index keys to be 1-tuples, not strings.  | 
1637  | 
(('parent', ), ' 100 78'),  | 
1638  | 
(('separate', ), '')])  | 
|
| 
2592.3.34
by Robert Collins
 Rough unfactored support for parentless KnitGraphIndexs.  | 
1639  | 
combined_index = CombinedGraphIndex([index1, index2])  | 
1640  | 
if catch_adds:  | 
|
1641  | 
self.combined_index = combined_index  | 
|
1642  | 
self.caught_entries = []  | 
|
1643  | 
add_callback = self.catch_add  | 
|
1644  | 
else:  | 
|
1645  | 
add_callback = None  | 
|
| 
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.  | 
1646  | 
return _KnitGraphIndex(combined_index, lambda:True, parents=False,  | 
| 
2592.3.34
by Robert Collins
 Rough unfactored support for parentless KnitGraphIndexs.  | 
1647  | 
add_callback=add_callback)  | 
1648  | 
||
| 
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.  | 
1649  | 
def test_keys(self):  | 
1650  | 
index = self.two_graph_index()  | 
|
1651  | 
self.assertEqual(set([('tail',), ('tip',), ('parent',), ('separate',)]),  | 
|
1652  | 
set(index.keys()))  | 
|
| 
2592.3.34
by Robert Collins
 Rough unfactored support for parentless KnitGraphIndexs.  | 
1653  | 
|
1654  | 
def test_get_position(self):  | 
|
1655  | 
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.  | 
1656  | 
self.assertEqual((index._graph_index._indices[0], 0, 100),  | 
1657  | 
index.get_position(('tip',)))  | 
|
1658  | 
self.assertEqual((index._graph_index._indices[1], 100, 78),  | 
|
1659  | 
index.get_position(('parent',)))  | 
|
| 
2592.3.34
by Robert Collins
 Rough unfactored support for parentless KnitGraphIndexs.  | 
1660  | 
|
1661  | 
def test_get_method(self):  | 
|
1662  | 
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.  | 
1663  | 
self.assertEqual('fulltext', index.get_method(('tip',)))  | 
1664  | 
self.assertEqual(['fulltext'], index.get_options(('parent',)))  | 
|
| 
2592.3.34
by Robert Collins
 Rough unfactored support for parentless KnitGraphIndexs.  | 
1665  | 
|
1666  | 
def test_get_options(self):  | 
|
1667  | 
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.  | 
1668  | 
self.assertEqual(['fulltext', 'no-eol'], index.get_options(('tip',)))  | 
1669  | 
self.assertEqual(['fulltext'], index.get_options(('parent',)))  | 
|
1670  | 
||
1671  | 
def test_get_parent_map(self):  | 
|
1672  | 
index = self.two_graph_index()  | 
|
1673  | 
self.assertEqual({('parent',):None},  | 
|
1674  | 
index.get_parent_map([('parent',), ('ghost',)]))  | 
|
| 
2592.3.34
by Robert Collins
 Rough unfactored support for parentless KnitGraphIndexs.  | 
1675  | 
|
1676  | 
def catch_add(self, entries):  | 
|
1677  | 
self.caught_entries.append(entries)  | 
|
1678  | 
||
1679  | 
def test_add_no_callback_errors(self):  | 
|
1680  | 
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.  | 
1681  | 
self.assertRaises(errors.ReadOnlyError, index.add_records,  | 
1682  | 
[(('new',), 'fulltext,no-eol', (None, 50, 60), [('separate',)])])  | 
|
| 
2592.3.34
by Robert Collins
 Rough unfactored support for parentless KnitGraphIndexs.  | 
1683  | 
|
1684  | 
def test_add_version_smoke(self):  | 
|
1685  | 
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.  | 
1686  | 
index.add_records([(('new',), 'fulltext,no-eol', (None, 50, 60), [])])  | 
| 
2624.2.5
by Robert Collins
 Change bzrlib.index.Index keys to be 1-tuples, not strings.  | 
1687  | 
self.assertEqual([[(('new', ), 'N50 60')]],  | 
| 
2592.3.34
by Robert Collins
 Rough unfactored support for parentless KnitGraphIndexs.  | 
1688  | 
self.caught_entries)  | 
1689  | 
||
1690  | 
def test_add_version_delta_not_delta_index(self):  | 
|
1691  | 
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.  | 
1692  | 
self.assertRaises(errors.KnitCorrupt, index.add_records,  | 
1693  | 
[(('new',), 'no-eol,line-delta', (None, 0, 100), [])])  | 
|
| 
2592.3.34
by Robert Collins
 Rough unfactored support for parentless KnitGraphIndexs.  | 
1694  | 
self.assertEqual([], self.caught_entries)  | 
1695  | 
||
1696  | 
def test_add_version_same_dup(self):  | 
|
1697  | 
index = self.two_graph_index(catch_adds=True)  | 
|
1698  | 
        # options can be spelt two different ways
 | 
|
| 
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.  | 
1699  | 
index.add_records([(('tip',), 'fulltext,no-eol', (None, 0, 100), [])])  | 
1700  | 
index.add_records([(('tip',), 'no-eol,fulltext', (None, 0, 100), [])])  | 
|
1701  | 
        # position/length are ignored (because each pack could have fulltext or
 | 
|
1702  | 
        # delta, and be at a different position.
 | 
|
1703  | 
index.add_records([(('tip',), 'fulltext,no-eol', (None, 50, 100), [])])  | 
|
1704  | 
index.add_records([(('tip',), 'fulltext,no-eol', (None, 0, 1000), [])])  | 
|
| 
2592.3.34
by Robert Collins
 Rough unfactored support for parentless KnitGraphIndexs.  | 
1705  | 
        # 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.  | 
1706  | 
self.assertEqual([[], [], [], []], self.caught_entries)  | 
| 
2592.3.34
by Robert Collins
 Rough unfactored support for parentless KnitGraphIndexs.  | 
1707  | 
|
1708  | 
def test_add_version_different_dup(self):  | 
|
1709  | 
index = self.two_graph_index(catch_adds=True)  | 
|
1710  | 
        # change options
 | 
|
| 
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.KnitCorrupt, index.add_records,  | 
1712  | 
[(('tip',), 'no-eol,line-delta', (None, 0, 100), [])])  | 
|
1713  | 
self.assertRaises(errors.KnitCorrupt, index.add_records,  | 
|
1714  | 
[(('tip',), 'line-delta,no-eol', (None, 0, 100), [])])  | 
|
1715  | 
self.assertRaises(errors.KnitCorrupt, index.add_records,  | 
|
1716  | 
[(('tip',), 'fulltext', (None, 0, 100), [])])  | 
|
| 
2592.3.34
by Robert Collins
 Rough unfactored support for parentless KnitGraphIndexs.  | 
1717  | 
        # parents
 | 
| 
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.  | 
1718  | 
self.assertRaises(errors.KnitCorrupt, index.add_records,  | 
1719  | 
[(('tip',), 'fulltext,no-eol', (None, 0, 100), [('parent',)])])  | 
|
| 
2592.3.34
by Robert Collins
 Rough unfactored support for parentless KnitGraphIndexs.  | 
1720  | 
self.assertEqual([], self.caught_entries)  | 
1721  | 
||
1722  | 
def test_add_versions(self):  | 
|
1723  | 
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.  | 
1724  | 
index.add_records([  | 
1725  | 
(('new',), 'fulltext,no-eol', (None, 50, 60), []),  | 
|
1726  | 
(('new2',), 'fulltext', (None, 0, 6), []),  | 
|
| 
2592.3.34
by Robert Collins
 Rough unfactored support for parentless KnitGraphIndexs.  | 
1727  | 
                ])
 | 
| 
2624.2.5
by Robert Collins
 Change bzrlib.index.Index keys to be 1-tuples, not strings.  | 
1728  | 
self.assertEqual([(('new', ), 'N50 60'), (('new2', ), ' 0 6')],  | 
| 
2592.3.34
by Robert Collins
 Rough unfactored support for parentless KnitGraphIndexs.  | 
1729  | 
sorted(self.caught_entries[0]))  | 
1730  | 
self.assertEqual(1, len(self.caught_entries))  | 
|
1731  | 
||
1732  | 
def test_add_versions_delta_not_delta_index(self):  | 
|
1733  | 
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.  | 
1734  | 
self.assertRaises(errors.KnitCorrupt, index.add_records,  | 
1735  | 
[(('new',), 'no-eol,line-delta', (None, 0, 100), [('parent',)])])  | 
|
| 
2592.3.34
by Robert Collins
 Rough unfactored support for parentless KnitGraphIndexs.  | 
1736  | 
self.assertEqual([], self.caught_entries)  | 
1737  | 
||
1738  | 
def test_add_versions_parents_not_parents_index(self):  | 
|
1739  | 
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.  | 
1740  | 
self.assertRaises(errors.KnitCorrupt, index.add_records,  | 
1741  | 
[(('new',), 'no-eol,fulltext', (None, 0, 100), [('parent',)])])  | 
|
| 
2592.3.34
by Robert Collins
 Rough unfactored support for parentless KnitGraphIndexs.  | 
1742  | 
self.assertEqual([], self.caught_entries)  | 
1743  | 
||
| 
2841.2.1
by Robert Collins
 * Commit no longer checks for new text keys during insertion when the  | 
1744  | 
def test_add_versions_random_id_accepted(self):  | 
1745  | 
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.  | 
1746  | 
index.add_records([], random_id=True)  | 
| 
2841.2.1
by Robert Collins
 * Commit no longer checks for new text keys during insertion when the  | 
1747  | 
|
| 
2592.3.34
by Robert Collins
 Rough unfactored support for parentless KnitGraphIndexs.  | 
1748  | 
def test_add_versions_same_dup(self):  | 
1749  | 
index = self.two_graph_index(catch_adds=True)  | 
|
1750  | 
        # options can be spelt two different ways
 | 
|
| 
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.  | 
1751  | 
index.add_records([(('tip',), 'fulltext,no-eol', (None, 0, 100), [])])  | 
1752  | 
index.add_records([(('tip',), 'no-eol,fulltext', (None, 0, 100), [])])  | 
|
1753  | 
        # position/length are ignored (because each pack could have fulltext or
 | 
|
1754  | 
        # delta, and be at a different position.
 | 
|
1755  | 
index.add_records([(('tip',), 'fulltext,no-eol', (None, 50, 100), [])])  | 
|
1756  | 
index.add_records([(('tip',), 'fulltext,no-eol', (None, 0, 1000), [])])  | 
|
| 
2592.3.34
by Robert Collins
 Rough unfactored support for parentless KnitGraphIndexs.  | 
1757  | 
        # 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.  | 
1758  | 
self.assertEqual([[], [], [], []], self.caught_entries)  | 
| 
2592.3.34
by Robert Collins
 Rough unfactored support for parentless KnitGraphIndexs.  | 
1759  | 
|
1760  | 
def test_add_versions_different_dup(self):  | 
|
1761  | 
index = self.two_graph_index(catch_adds=True)  | 
|
1762  | 
        # change options
 | 
|
| 
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.  | 
1763  | 
self.assertRaises(errors.KnitCorrupt, index.add_records,  | 
1764  | 
[(('tip',), 'no-eol,line-delta', (None, 0, 100), [])])  | 
|
1765  | 
self.assertRaises(errors.KnitCorrupt, index.add_records,  | 
|
1766  | 
[(('tip',), 'line-delta,no-eol', (None, 0, 100), [])])  | 
|
1767  | 
self.assertRaises(errors.KnitCorrupt, index.add_records,  | 
|
1768  | 
[(('tip',), 'fulltext', (None, 0, 100), [])])  | 
|
| 
2592.3.34
by Robert Collins
 Rough unfactored support for parentless KnitGraphIndexs.  | 
1769  | 
        # parents
 | 
| 
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.  | 
1770  | 
self.assertRaises(errors.KnitCorrupt, index.add_records,  | 
1771  | 
[(('tip',), 'fulltext,no-eol', (None, 0, 100), [('parent',)])])  | 
|
| 
2592.3.34
by Robert Collins
 Rough unfactored support for parentless KnitGraphIndexs.  | 
1772  | 
        # change options in the second record
 | 
| 
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.  | 
1773  | 
self.assertRaises(errors.KnitCorrupt, index.add_records,  | 
1774  | 
[(('tip',), 'fulltext,no-eol', (None, 0, 100), []),  | 
|
1775  | 
(('tip',), 'no-eol,line-delta', (None, 0, 100), [])])  | 
|
| 
2592.3.34
by Robert Collins
 Rough unfactored support for parentless KnitGraphIndexs.  | 
1776  | 
self.assertEqual([], self.caught_entries)  | 
| 
3350.8.1
by Robert Collins
 KnitVersionedFiles.add_fallback_versioned_files exists.  | 
1777  | 
|
1778  | 
||
1779  | 
class TestStacking(KnitTests):  | 
|
1780  | 
||
1781  | 
def get_basis_and_test_knit(self):  | 
|
1782  | 
basis = self.make_test_knit(name='basis')  | 
|
| 
3350.8.2
by Robert Collins
 stacked get_parent_map.  | 
1783  | 
basis = RecordingVersionedFilesDecorator(basis)  | 
| 
3350.8.1
by Robert Collins
 KnitVersionedFiles.add_fallback_versioned_files exists.  | 
1784  | 
test = self.make_test_knit(name='test')  | 
1785  | 
test.add_fallback_versioned_files(basis)  | 
|
1786  | 
return basis, test  | 
|
1787  | 
||
1788  | 
def test_add_fallback_versioned_files(self):  | 
|
1789  | 
basis = self.make_test_knit(name='basis')  | 
|
1790  | 
test = self.make_test_knit(name='test')  | 
|
1791  | 
        # It must not error; other tests test that the fallback is referred to
 | 
|
1792  | 
        # when accessing data.
 | 
|
1793  | 
test.add_fallback_versioned_files(basis)  | 
|
1794  | 
||
1795  | 
def test_add_lines(self):  | 
|
| 
3350.8.9
by Robert Collins
 define behaviour for add_lines with stacked storage.  | 
1796  | 
        # lines added to the test are not added to the basis
 | 
1797  | 
basis, test = self.get_basis_and_test_knit()  | 
|
1798  | 
key = ('foo',)  | 
|
1799  | 
key_basis = ('bar',)  | 
|
1800  | 
key_cross_border = ('quux',)  | 
|
1801  | 
key_delta = ('zaphod',)  | 
|
1802  | 
test.add_lines(key, (), ['foo\n'])  | 
|
1803  | 
self.assertEqual({}, basis.get_parent_map([key]))  | 
|
1804  | 
        # lines added to the test that reference across the stack do a
 | 
|
1805  | 
        # fulltext.
 | 
|
1806  | 
basis.add_lines(key_basis, (), ['foo\n'])  | 
|
1807  | 
basis.calls = []  | 
|
1808  | 
test.add_lines(key_cross_border, (key_basis,), ['foo\n'])  | 
|
1809  | 
self.assertEqual('fulltext', test._index.get_method(key_cross_border))  | 
|
| 
3830.3.10
by Martin Pool
 Update more stacking effort tests  | 
1810  | 
        # we don't even need to look at the basis to see that this should be
 | 
1811  | 
        # stored as a fulltext
 | 
|
1812  | 
self.assertEqual([], basis.calls)  | 
|
| 
3350.8.9
by Robert Collins
 define behaviour for add_lines with stacked storage.  | 
1813  | 
        # Subsequent adds do delta.
 | 
| 
3350.8.14
by Robert Collins
 Review feedback.  | 
1814  | 
basis.calls = []  | 
| 
3350.8.9
by Robert Collins
 define behaviour for add_lines with stacked storage.  | 
1815  | 
test.add_lines(key_delta, (key_cross_border,), ['foo\n'])  | 
1816  | 
self.assertEqual('line-delta', test._index.get_method(key_delta))  | 
|
1817  | 
self.assertEqual([], basis.calls)  | 
|
| 
3350.8.1
by Robert Collins
 KnitVersionedFiles.add_fallback_versioned_files exists.  | 
1818  | 
|
1819  | 
def test_annotate(self):  | 
|
| 
3350.8.8
by Robert Collins
 Stacking and knits don't play nice for annotation yet.  | 
1820  | 
        # annotations from the test knit are answered without asking the basis
 | 
1821  | 
basis, test = self.get_basis_and_test_knit()  | 
|
1822  | 
key = ('foo',)  | 
|
1823  | 
key_basis = ('bar',)  | 
|
1824  | 
key_missing = ('missing',)  | 
|
1825  | 
test.add_lines(key, (), ['foo\n'])  | 
|
1826  | 
details = test.annotate(key)  | 
|
1827  | 
self.assertEqual([(key, 'foo\n')], details)  | 
|
1828  | 
self.assertEqual([], basis.calls)  | 
|
1829  | 
        # But texts that are not in the test knit are looked for in the basis
 | 
|
1830  | 
        # directly.
 | 
|
1831  | 
basis.add_lines(key_basis, (), ['foo\n', 'bar\n'])  | 
|
1832  | 
basis.calls = []  | 
|
1833  | 
details = test.annotate(key_basis)  | 
|
1834  | 
self.assertEqual([(key_basis, 'foo\n'), (key_basis, 'bar\n')], details)  | 
|
| 
3350.9.1
by Robert Collins
 Redo annotate more simply, using just the public interfaces for VersionedFiles.  | 
1835  | 
        # Not optimised to date:
 | 
1836  | 
        # self.assertEqual([("annotate", key_basis)], basis.calls)
 | 
|
1837  | 
self.assertEqual([('get_parent_map', set([key_basis])),  | 
|
1838  | 
('get_parent_map', set([key_basis])),  | 
|
1839  | 
('get_parent_map', set([key_basis])),  | 
|
1840  | 
('get_record_stream', [key_basis], 'unordered', True)],  | 
|
1841  | 
basis.calls)  | 
|
| 
3350.8.1
by Robert Collins
 KnitVersionedFiles.add_fallback_versioned_files exists.  | 
1842  | 
|
1843  | 
def test_check(self):  | 
|
| 
3517.4.19
by Martin Pool
 Update test for knit.check() to expect it to recurse into fallback vfs  | 
1844  | 
        # At the moment checking a stacked knit does implicitly check the
 | 
1845  | 
        # fallback files.  
 | 
|
| 
3350.8.1
by Robert Collins
 KnitVersionedFiles.add_fallback_versioned_files exists.  | 
1846  | 
basis, test = self.get_basis_and_test_knit()  | 
1847  | 
test.check()  | 
|
1848  | 
||
1849  | 
def test_get_parent_map(self):  | 
|
| 
3350.8.2
by Robert Collins
 stacked get_parent_map.  | 
1850  | 
        # parents in the test knit are answered without asking the basis
 | 
1851  | 
basis, test = self.get_basis_and_test_knit()  | 
|
1852  | 
key = ('foo',)  | 
|
1853  | 
key_basis = ('bar',)  | 
|
1854  | 
key_missing = ('missing',)  | 
|
1855  | 
test.add_lines(key, (), [])  | 
|
1856  | 
parent_map = test.get_parent_map([key])  | 
|
1857  | 
self.assertEqual({key: ()}, parent_map)  | 
|
1858  | 
self.assertEqual([], basis.calls)  | 
|
1859  | 
        # But parents that are not in the test knit are looked for in the basis
 | 
|
1860  | 
basis.add_lines(key_basis, (), [])  | 
|
1861  | 
basis.calls = []  | 
|
1862  | 
parent_map = test.get_parent_map([key, key_basis, key_missing])  | 
|
1863  | 
self.assertEqual({key: (),  | 
|
1864  | 
key_basis: ()}, parent_map)  | 
|
1865  | 
self.assertEqual([("get_parent_map", set([key_basis, key_missing]))],  | 
|
1866  | 
basis.calls)  | 
|
| 
3350.8.1
by Robert Collins
 KnitVersionedFiles.add_fallback_versioned_files exists.  | 
1867  | 
|
| 
3350.8.7
by Robert Collins
 get_record_stream for fulltexts working (but note extreme memory use!).  | 
1868  | 
def test_get_record_stream_unordered_fulltexts(self):  | 
1869  | 
        # records from the test knit are answered without asking the basis:
 | 
|
1870  | 
basis, test = self.get_basis_and_test_knit()  | 
|
1871  | 
key = ('foo',)  | 
|
1872  | 
key_basis = ('bar',)  | 
|
1873  | 
key_missing = ('missing',)  | 
|
1874  | 
test.add_lines(key, (), ['foo\n'])  | 
|
1875  | 
records = list(test.get_record_stream([key], 'unordered', True))  | 
|
1876  | 
self.assertEqual(1, len(records))  | 
|
1877  | 
self.assertEqual([], basis.calls)  | 
|
1878  | 
        # Missing (from test knit) objects are retrieved from the basis:
 | 
|
1879  | 
basis.add_lines(key_basis, (), ['foo\n', 'bar\n'])  | 
|
1880  | 
basis.calls = []  | 
|
1881  | 
records = list(test.get_record_stream([key_basis, key_missing],  | 
|
1882  | 
'unordered', True))  | 
|
1883  | 
self.assertEqual(2, len(records))  | 
|
1884  | 
calls = list(basis.calls)  | 
|
1885  | 
for record in records:  | 
|
1886  | 
self.assertSubset([record.key], (key_basis, key_missing))  | 
|
1887  | 
if record.key == key_missing:  | 
|
1888  | 
self.assertIsInstance(record, AbsentContentFactory)  | 
|
1889  | 
else:  | 
|
1890  | 
reference = list(basis.get_record_stream([key_basis],  | 
|
1891  | 
'unordered', True))[0]  | 
|
1892  | 
self.assertEqual(reference.key, record.key)  | 
|
1893  | 
self.assertEqual(reference.sha1, record.sha1)  | 
|
1894  | 
self.assertEqual(reference.storage_kind, record.storage_kind)  | 
|
1895  | 
self.assertEqual(reference.get_bytes_as(reference.storage_kind),  | 
|
1896  | 
record.get_bytes_as(record.storage_kind))  | 
|
1897  | 
self.assertEqual(reference.get_bytes_as('fulltext'),  | 
|
1898  | 
record.get_bytes_as('fulltext'))  | 
|
| 
3350.8.14
by Robert Collins
 Review feedback.  | 
1899  | 
        # 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!).  | 
1900  | 
        # ask which fallbacks have which parents.
 | 
1901  | 
self.assertEqual([  | 
|
1902  | 
("get_parent_map", set([key_basis, key_missing])),  | 
|
1903  | 
("get_record_stream", [key_basis], 'unordered', True)],  | 
|
1904  | 
calls)  | 
|
1905  | 
||
1906  | 
def test_get_record_stream_ordered_fulltexts(self):  | 
|
1907  | 
        # ordering is preserved down into the fallback store.
 | 
|
1908  | 
basis, test = self.get_basis_and_test_knit()  | 
|
1909  | 
key = ('foo',)  | 
|
1910  | 
key_basis = ('bar',)  | 
|
1911  | 
key_basis_2 = ('quux',)  | 
|
1912  | 
key_missing = ('missing',)  | 
|
1913  | 
test.add_lines(key, (key_basis,), ['foo\n'])  | 
|
1914  | 
        # Missing (from test knit) objects are retrieved from the basis:
 | 
|
1915  | 
basis.add_lines(key_basis, (key_basis_2,), ['foo\n', 'bar\n'])  | 
|
1916  | 
basis.add_lines(key_basis_2, (), ['quux\n'])  | 
|
1917  | 
basis.calls = []  | 
|
1918  | 
        # ask for in non-topological order
 | 
|
1919  | 
records = list(test.get_record_stream(  | 
|
1920  | 
[key, key_basis, key_missing, key_basis_2], 'topological', True))  | 
|
1921  | 
self.assertEqual(4, len(records))  | 
|
1922  | 
results = []  | 
|
1923  | 
for record in records:  | 
|
1924  | 
self.assertSubset([record.key],  | 
|
1925  | 
(key_basis, key_missing, key_basis_2, key))  | 
|
1926  | 
if record.key == key_missing:  | 
|
1927  | 
self.assertIsInstance(record, AbsentContentFactory)  | 
|
1928  | 
else:  | 
|
1929  | 
results.append((record.key, record.sha1, record.storage_kind,  | 
|
1930  | 
record.get_bytes_as('fulltext')))  | 
|
1931  | 
calls = list(basis.calls)  | 
|
1932  | 
order = [record[0] for record in results]  | 
|
1933  | 
self.assertEqual([key_basis_2, key_basis, key], order)  | 
|
1934  | 
for result in results:  | 
|
1935  | 
if result[0] == key:  | 
|
1936  | 
source = test  | 
|
1937  | 
else:  | 
|
1938  | 
source = basis  | 
|
1939  | 
record = source.get_record_stream([result[0]], 'unordered',  | 
|
1940  | 
True).next()  | 
|
1941  | 
self.assertEqual(record.key, result[0])  | 
|
1942  | 
self.assertEqual(record.sha1, result[1])  | 
|
1943  | 
self.assertEqual(record.storage_kind, result[2])  | 
|
1944  | 
self.assertEqual(record.get_bytes_as('fulltext'), result[3])  | 
|
| 
3350.8.14
by Robert Collins
 Review feedback.  | 
1945  | 
        # 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!).  | 
1946  | 
        # ask which fallbacks have which parents.
 | 
1947  | 
self.assertEqual([  | 
|
1948  | 
("get_parent_map", set([key_basis, key_basis_2, key_missing])),  | 
|
1949  | 
            # unordered is asked for by the underlying worker as it still
 | 
|
1950  | 
            # buffers everything while answering - which is a problem!
 | 
|
1951  | 
("get_record_stream", [key_basis_2, key_basis], 'unordered', True)],  | 
|
1952  | 
calls)  | 
|
1953  | 
||
| 
3350.8.6
by Robert Collins
 get_record_stream stacking for delta access.  | 
1954  | 
def test_get_record_stream_unordered_deltas(self):  | 
1955  | 
        # records from the test knit are answered without asking the basis:
 | 
|
1956  | 
basis, test = self.get_basis_and_test_knit()  | 
|
1957  | 
key = ('foo',)  | 
|
1958  | 
key_basis = ('bar',)  | 
|
1959  | 
key_missing = ('missing',)  | 
|
1960  | 
test.add_lines(key, (), ['foo\n'])  | 
|
1961  | 
records = list(test.get_record_stream([key], 'unordered', False))  | 
|
1962  | 
self.assertEqual(1, len(records))  | 
|
1963  | 
self.assertEqual([], basis.calls)  | 
|
1964  | 
        # Missing (from test knit) objects are retrieved from the basis:
 | 
|
1965  | 
basis.add_lines(key_basis, (), ['foo\n', 'bar\n'])  | 
|
1966  | 
basis.calls = []  | 
|
1967  | 
records = list(test.get_record_stream([key_basis, key_missing],  | 
|
1968  | 
'unordered', False))  | 
|
1969  | 
self.assertEqual(2, len(records))  | 
|
1970  | 
calls = list(basis.calls)  | 
|
1971  | 
for record in records:  | 
|
1972  | 
self.assertSubset([record.key], (key_basis, key_missing))  | 
|
1973  | 
if record.key == key_missing:  | 
|
1974  | 
self.assertIsInstance(record, AbsentContentFactory)  | 
|
1975  | 
else:  | 
|
1976  | 
reference = list(basis.get_record_stream([key_basis],  | 
|
1977  | 
'unordered', False))[0]  | 
|
1978  | 
self.assertEqual(reference.key, record.key)  | 
|
1979  | 
self.assertEqual(reference.sha1, record.sha1)  | 
|
1980  | 
self.assertEqual(reference.storage_kind, record.storage_kind)  | 
|
1981  | 
self.assertEqual(reference.get_bytes_as(reference.storage_kind),  | 
|
1982  | 
record.get_bytes_as(record.storage_kind))  | 
|
| 
3350.8.14
by Robert Collins
 Review feedback.  | 
1983  | 
        # 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.  | 
1984  | 
        # ask which fallbacks have which parents.
 | 
1985  | 
self.assertEqual([  | 
|
1986  | 
("get_parent_map", set([key_basis, key_missing])),  | 
|
1987  | 
("get_record_stream", [key_basis], 'unordered', False)],  | 
|
1988  | 
calls)  | 
|
1989  | 
||
1990  | 
def test_get_record_stream_ordered_deltas(self):  | 
|
1991  | 
        # ordering is preserved down into the fallback store.
 | 
|
1992  | 
basis, test = self.get_basis_and_test_knit()  | 
|
1993  | 
key = ('foo',)  | 
|
1994  | 
key_basis = ('bar',)  | 
|
1995  | 
key_basis_2 = ('quux',)  | 
|
1996  | 
key_missing = ('missing',)  | 
|
1997  | 
test.add_lines(key, (key_basis,), ['foo\n'])  | 
|
1998  | 
        # Missing (from test knit) objects are retrieved from the basis:
 | 
|
1999  | 
basis.add_lines(key_basis, (key_basis_2,), ['foo\n', 'bar\n'])  | 
|
2000  | 
basis.add_lines(key_basis_2, (), ['quux\n'])  | 
|
2001  | 
basis.calls = []  | 
|
2002  | 
        # ask for in non-topological order
 | 
|
2003  | 
records = list(test.get_record_stream(  | 
|
2004  | 
[key, key_basis, key_missing, key_basis_2], 'topological', False))  | 
|
2005  | 
self.assertEqual(4, len(records))  | 
|
2006  | 
results = []  | 
|
2007  | 
for record in records:  | 
|
2008  | 
self.assertSubset([record.key],  | 
|
2009  | 
(key_basis, key_missing, key_basis_2, key))  | 
|
2010  | 
if record.key == key_missing:  | 
|
2011  | 
self.assertIsInstance(record, AbsentContentFactory)  | 
|
2012  | 
else:  | 
|
2013  | 
results.append((record.key, record.sha1, record.storage_kind,  | 
|
2014  | 
record.get_bytes_as(record.storage_kind)))  | 
|
2015  | 
calls = list(basis.calls)  | 
|
2016  | 
order = [record[0] for record in results]  | 
|
2017  | 
self.assertEqual([key_basis_2, key_basis, key], order)  | 
|
2018  | 
for result in results:  | 
|
2019  | 
if result[0] == key:  | 
|
2020  | 
source = test  | 
|
2021  | 
else:  | 
|
2022  | 
source = basis  | 
|
2023  | 
record = source.get_record_stream([result[0]], 'unordered',  | 
|
2024  | 
False).next()  | 
|
2025  | 
self.assertEqual(record.key, result[0])  | 
|
2026  | 
self.assertEqual(record.sha1, result[1])  | 
|
2027  | 
self.assertEqual(record.storage_kind, result[2])  | 
|
2028  | 
self.assertEqual(record.get_bytes_as(record.storage_kind), result[3])  | 
|
| 
3350.8.14
by Robert Collins
 Review feedback.  | 
2029  | 
        # 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.  | 
2030  | 
        # ask which fallbacks have which parents.
 | 
2031  | 
self.assertEqual([  | 
|
2032  | 
("get_parent_map", set([key_basis, key_basis_2, key_missing])),  | 
|
2033  | 
("get_record_stream", [key_basis_2, key_basis], 'topological', False)],  | 
|
2034  | 
calls)  | 
|
| 
3350.8.1
by Robert Collins
 KnitVersionedFiles.add_fallback_versioned_files exists.  | 
2035  | 
|
2036  | 
def test_get_sha1s(self):  | 
|
| 
3350.8.3
by Robert Collins
 VF.get_sha1s needed changing to be stackable.  | 
2037  | 
        # sha1's in the test knit are answered without asking the basis
 | 
2038  | 
basis, test = self.get_basis_and_test_knit()  | 
|
2039  | 
key = ('foo',)  | 
|
2040  | 
key_basis = ('bar',)  | 
|
2041  | 
key_missing = ('missing',)  | 
|
2042  | 
test.add_lines(key, (), ['foo\n'])  | 
|
| 
3734.2.4
by Vincent Ladeuil
 Fix python2.6 deprecation warnings related to hashlib.  | 
2043  | 
key_sha1sum = osutils.sha('foo\n').hexdigest()  | 
| 
3350.8.3
by Robert Collins
 VF.get_sha1s needed changing to be stackable.  | 
2044  | 
sha1s = test.get_sha1s([key])  | 
2045  | 
self.assertEqual({key: key_sha1sum}, sha1s)  | 
|
2046  | 
self.assertEqual([], basis.calls)  | 
|
2047  | 
        # But texts that are not in the test knit are looked for in the basis
 | 
|
2048  | 
        # directly (rather than via text reconstruction) so that remote servers
 | 
|
2049  | 
        # etc don't have to answer with full content.
 | 
|
2050  | 
basis.add_lines(key_basis, (), ['foo\n', 'bar\n'])  | 
|
| 
3734.2.4
by Vincent Ladeuil
 Fix python2.6 deprecation warnings related to hashlib.  | 
2051  | 
basis_sha1sum = osutils.sha('foo\nbar\n').hexdigest()  | 
| 
3350.8.3
by Robert Collins
 VF.get_sha1s needed changing to be stackable.  | 
2052  | 
basis.calls = []  | 
2053  | 
sha1s = test.get_sha1s([key, key_missing, key_basis])  | 
|
2054  | 
self.assertEqual({key: key_sha1sum,  | 
|
2055  | 
key_basis: basis_sha1sum}, sha1s)  | 
|
2056  | 
self.assertEqual([("get_sha1s", set([key_basis, key_missing]))],  | 
|
2057  | 
basis.calls)  | 
|
| 
3350.8.1
by Robert Collins
 KnitVersionedFiles.add_fallback_versioned_files exists.  | 
2058  | 
|
2059  | 
def test_insert_record_stream(self):  | 
|
| 
3350.8.10
by Robert Collins
 Stacked insert_record_stream.  | 
2060  | 
        # records are inserted as normal; insert_record_stream builds on
 | 
| 
3350.8.14
by Robert Collins
 Review feedback.  | 
2061  | 
        # add_lines, so a smoke test should be all that's needed:
 | 
| 
3350.8.10
by Robert Collins
 Stacked insert_record_stream.  | 
2062  | 
key = ('foo',)  | 
2063  | 
key_basis = ('bar',)  | 
|
2064  | 
key_delta = ('zaphod',)  | 
|
2065  | 
basis, test = self.get_basis_and_test_knit()  | 
|
2066  | 
source = self.make_test_knit(name='source')  | 
|
2067  | 
basis.add_lines(key_basis, (), ['foo\n'])  | 
|
2068  | 
basis.calls = []  | 
|
2069  | 
source.add_lines(key_basis, (), ['foo\n'])  | 
|
2070  | 
source.add_lines(key_delta, (key_basis,), ['bar\n'])  | 
|
2071  | 
stream = source.get_record_stream([key_delta], 'unordered', False)  | 
|
2072  | 
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  | 
2073  | 
        # XXX: this does somewhat too many calls in making sure of whether it
 | 
2074  | 
        # has to recreate the full text.
 | 
|
2075  | 
self.assertEqual([("get_parent_map", set([key_basis])),  | 
|
2076  | 
('get_parent_map', set([key_basis])),  | 
|
| 
3830.3.10
by Martin Pool
 Update more stacking effort tests  | 
2077  | 
('get_record_stream', [key_basis], 'unordered', True)],  | 
| 
3350.8.10
by Robert Collins
 Stacked insert_record_stream.  | 
2078  | 
basis.calls)  | 
2079  | 
self.assertEqual({key_delta:(key_basis,)},  | 
|
2080  | 
test.get_parent_map([key_delta]))  | 
|
2081  | 
self.assertEqual('bar\n', test.get_record_stream([key_delta],  | 
|
2082  | 
'unordered', True).next().get_bytes_as('fulltext'))  | 
|
| 
3350.8.1
by Robert Collins
 KnitVersionedFiles.add_fallback_versioned_files exists.  | 
2083  | 
|
2084  | 
def test_iter_lines_added_or_present_in_keys(self):  | 
|
| 
3350.8.5
by Robert Collins
 Iter_lines_added_or_present_in_keys stacks.  | 
2085  | 
        # Lines from the basis are returned, and lines for a given key are only
 | 
2086  | 
        # returned once. 
 | 
|
2087  | 
key1 = ('foo1',)  | 
|
2088  | 
key2 = ('foo2',)  | 
|
2089  | 
        # all sources are asked for keys:
 | 
|
2090  | 
basis, test = self.get_basis_and_test_knit()  | 
|
2091  | 
basis.add_lines(key1, (), ["foo"])  | 
|
2092  | 
basis.calls = []  | 
|
2093  | 
lines = list(test.iter_lines_added_or_present_in_keys([key1]))  | 
|
2094  | 
self.assertEqual([("foo\n", key1)], lines)  | 
|
2095  | 
self.assertEqual([("iter_lines_added_or_present_in_keys", set([key1]))],  | 
|
2096  | 
basis.calls)  | 
|
2097  | 
        # keys in both are not duplicated:
 | 
|
2098  | 
test.add_lines(key2, (), ["bar\n"])  | 
|
2099  | 
basis.add_lines(key2, (), ["bar\n"])  | 
|
2100  | 
basis.calls = []  | 
|
2101  | 
lines = list(test.iter_lines_added_or_present_in_keys([key2]))  | 
|
2102  | 
self.assertEqual([("bar\n", key2)], lines)  | 
|
2103  | 
self.assertEqual([], basis.calls)  | 
|
| 
3350.8.1
by Robert Collins
 KnitVersionedFiles.add_fallback_versioned_files exists.  | 
2104  | 
|
2105  | 
def test_keys(self):  | 
|
| 
3350.8.4
by Robert Collins
 Vf.keys() stacking support.  | 
2106  | 
key1 = ('foo1',)  | 
2107  | 
key2 = ('foo2',)  | 
|
2108  | 
        # all sources are asked for keys:
 | 
|
2109  | 
basis, test = self.get_basis_and_test_knit()  | 
|
2110  | 
keys = test.keys()  | 
|
2111  | 
self.assertEqual(set(), set(keys))  | 
|
2112  | 
self.assertEqual([("keys",)], basis.calls)  | 
|
2113  | 
        # keys from a basis are returned:
 | 
|
2114  | 
basis.add_lines(key1, (), [])  | 
|
2115  | 
basis.calls = []  | 
|
2116  | 
keys = test.keys()  | 
|
2117  | 
self.assertEqual(set([key1]), set(keys))  | 
|
2118  | 
self.assertEqual([("keys",)], basis.calls)  | 
|
2119  | 
        # keys in both are not duplicated:
 | 
|
2120  | 
test.add_lines(key2, (), [])  | 
|
2121  | 
basis.add_lines(key2, (), [])  | 
|
2122  | 
basis.calls = []  | 
|
2123  | 
keys = test.keys()  | 
|
2124  | 
self.assertEqual(2, len(keys))  | 
|
2125  | 
self.assertEqual(set([key1, key2]), set(keys))  | 
|
2126  | 
self.assertEqual([("keys",)], basis.calls)  | 
|
| 
3350.8.1
by Robert Collins
 KnitVersionedFiles.add_fallback_versioned_files exists.  | 
2127  | 
|
2128  | 
def test_add_mpdiffs(self):  | 
|
| 
3350.8.11
by Robert Collins
 Stacked add_mpdiffs.  | 
2129  | 
        # records are inserted as normal; add_mpdiff builds on
 | 
| 
3350.8.14
by Robert Collins
 Review feedback.  | 
2130  | 
        # add_lines, so a smoke test should be all that's needed:
 | 
| 
3350.8.11
by Robert Collins
 Stacked add_mpdiffs.  | 
2131  | 
key = ('foo',)  | 
2132  | 
key_basis = ('bar',)  | 
|
2133  | 
key_delta = ('zaphod',)  | 
|
2134  | 
basis, test = self.get_basis_and_test_knit()  | 
|
2135  | 
source = self.make_test_knit(name='source')  | 
|
2136  | 
basis.add_lines(key_basis, (), ['foo\n'])  | 
|
2137  | 
basis.calls = []  | 
|
2138  | 
source.add_lines(key_basis, (), ['foo\n'])  | 
|
2139  | 
source.add_lines(key_delta, (key_basis,), ['bar\n'])  | 
|
2140  | 
diffs = source.make_mpdiffs([key_delta])  | 
|
2141  | 
test.add_mpdiffs([(key_delta, (key_basis,),  | 
|
2142  | 
source.get_sha1s([key_delta])[key_delta], diffs[0])])  | 
|
2143  | 
self.assertEqual([("get_parent_map", set([key_basis])),  | 
|
| 
3830.3.10
by Martin Pool
 Update more stacking effort tests  | 
2144  | 
('get_record_stream', [key_basis], 'unordered', True),],  | 
| 
3350.8.11
by Robert Collins
 Stacked add_mpdiffs.  | 
2145  | 
basis.calls)  | 
2146  | 
self.assertEqual({key_delta:(key_basis,)},  | 
|
2147  | 
test.get_parent_map([key_delta]))  | 
|
2148  | 
self.assertEqual('bar\n', test.get_record_stream([key_delta],  | 
|
2149  | 
'unordered', True).next().get_bytes_as('fulltext'))  | 
|
| 
3350.8.1
by Robert Collins
 KnitVersionedFiles.add_fallback_versioned_files exists.  | 
2150  | 
|
2151  | 
def test_make_mpdiffs(self):  | 
|
| 
3350.8.12
by Robert Collins
 Stacked make_mpdiffs.  | 
2152  | 
        # Generating an mpdiff across a stacking boundary should detect parent
 | 
2153  | 
        # texts regions.
 | 
|
2154  | 
key = ('foo',)  | 
|
2155  | 
key_left = ('bar',)  | 
|
2156  | 
key_right = ('zaphod',)  | 
|
2157  | 
basis, test = self.get_basis_and_test_knit()  | 
|
2158  | 
basis.add_lines(key_left, (), ['bar\n'])  | 
|
2159  | 
basis.add_lines(key_right, (), ['zaphod\n'])  | 
|
2160  | 
basis.calls = []  | 
|
2161  | 
test.add_lines(key, (key_left, key_right),  | 
|
2162  | 
['bar\n', 'foo\n', 'zaphod\n'])  | 
|
2163  | 
diffs = test.make_mpdiffs([key])  | 
|
2164  | 
self.assertEqual([  | 
|
2165  | 
multiparent.MultiParent([multiparent.ParentText(0, 0, 0, 1),  | 
|
2166  | 
multiparent.NewText(['foo\n']),  | 
|
2167  | 
multiparent.ParentText(1, 0, 2, 1)])],  | 
|
2168  | 
diffs)  | 
|
| 
3830.3.10
by Martin Pool
 Update more stacking effort tests  | 
2169  | 
self.assertEqual(3, len(basis.calls))  | 
| 
3350.8.12
by Robert Collins
 Stacked make_mpdiffs.  | 
2170  | 
self.assertEqual([  | 
2171  | 
("get_parent_map", set([key_left, key_right])),  | 
|
2172  | 
("get_parent_map", set([key_left, key_right])),  | 
|
2173  | 
            ],
 | 
|
| 
3830.3.10
by Martin Pool
 Update more stacking effort tests  | 
2174  | 
basis.calls[:-1])  | 
2175  | 
last_call = basis.calls[-1]  | 
|
| 
3350.8.14
by Robert Collins
 Review feedback.  | 
2176  | 
self.assertEqual('get_record_stream', last_call[0])  | 
2177  | 
self.assertEqual(set([key_left, key_right]), set(last_call[1]))  | 
|
2178  | 
self.assertEqual('unordered', last_call[2])  | 
|
2179  | 
self.assertEqual(True, last_call[3])  |