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 |
22 |
import sha |
|
2484.1.17
by John Arbash Meinel
Workaround for Pyrex <0.9.5 and python >=2.5 incompatibilities. |
23 |
import sys |
1563.2.4
by Robert Collins
First cut at including the knit implementation of versioned_file. |
24 |
|
2196.2.5
by John Arbash Meinel
Add an exception class when the knit index storage method is unknown, and properly test for it |
25 |
from bzrlib import ( |
26 |
errors, |
|
2484.1.5
by John Arbash Meinel
Simplistic implementations of custom parsers for options and parents |
27 |
generate_ids, |
2484.1.1
by John Arbash Meinel
Add an initial function to read knit indexes in pyrex. |
28 |
knit, |
2196.2.5
by John Arbash Meinel
Add an exception class when the knit index storage method is unknown, and properly test for it |
29 |
)
|
2158.3.1
by Dmitry Vasiliev
KnitIndex tests/fixes/optimizations |
30 |
from bzrlib.errors import ( |
31 |
RevisionAlreadyPresent, |
|
32 |
KnitHeaderError, |
|
33 |
RevisionNotPresent, |
|
34 |
NoSuchFile, |
|
35 |
)
|
|
1684.3.3
by Robert Collins
Add a special cased weaves to knit converter. |
36 |
from bzrlib.knit import ( |
2151.1.1
by John Arbash Meinel
(Dmitry Vasiliev) Tune KnitContent and add tests |
37 |
KnitContent, |
1684.3.3
by Robert Collins
Add a special cased weaves to knit converter. |
38 |
KnitVersionedFile, |
39 |
KnitPlainFactory, |
|
40 |
KnitAnnotateFactory, |
|
2329.1.1
by John Arbash Meinel
Update _KnitData parser to raise more helpful errors when it detects corruption. |
41 |
_KnitData, |
2158.3.1
by Dmitry Vasiliev
KnitIndex tests/fixes/optimizations |
42 |
_KnitIndex, |
43 |
WeaveToKnit, |
|
2520.4.41
by Aaron Bentley
Accelerate mpdiff generation |
44 |
KnitSequenceMatcher, |
2158.3.1
by Dmitry Vasiliev
KnitIndex tests/fixes/optimizations |
45 |
)
|
1563.2.4
by Robert Collins
First cut at including the knit implementation of versioned_file. |
46 |
from bzrlib.osutils import split_lines |
2484.1.1
by John Arbash Meinel
Add an initial function to read knit indexes in pyrex. |
47 |
from bzrlib.tests import TestCase, TestCaseWithTransport, Feature |
1685.1.39
by John Arbash Meinel
Updating test_knit to not instantiate a LocalTransport directly. |
48 |
from bzrlib.transport import TransportLogger, get_transport |
1563.2.13
by Robert Collins
InterVersionedFile implemented. |
49 |
from bzrlib.transport.memory import MemoryTransport |
1684.3.3
by Robert Collins
Add a special cased weaves to knit converter. |
50 |
from bzrlib.weave import Weave |
51 |
||
52 |
||
2484.1.1
by John Arbash Meinel
Add an initial function to read knit indexes in pyrex. |
53 |
class _CompiledKnitFeature(Feature): |
54 |
||
55 |
def _probe(self): |
|
56 |
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 |
57 |
import bzrlib._knit_load_data_c |
2484.1.1
by John Arbash Meinel
Add an initial function to read knit indexes in pyrex. |
58 |
except ImportError: |
59 |
return False |
|
60 |
return True |
|
61 |
||
62 |
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 |
63 |
return 'bzrlib._knit_load_data_c' |
2484.1.1
by John Arbash Meinel
Add an initial function to read knit indexes in pyrex. |
64 |
|
65 |
CompiledKnitFeature = _CompiledKnitFeature() |
|
66 |
||
67 |
||
2151.1.1
by John Arbash Meinel
(Dmitry Vasiliev) Tune KnitContent and add tests |
68 |
class KnitContentTests(TestCase): |
69 |
||
70 |
def test_constructor(self): |
|
71 |
content = KnitContent([]) |
|
72 |
||
73 |
def test_text(self): |
|
74 |
content = KnitContent([]) |
|
75 |
self.assertEqual(content.text(), []) |
|
76 |
||
77 |
content = KnitContent([("origin1", "text1"), ("origin2", "text2")]) |
|
78 |
self.assertEqual(content.text(), ["text1", "text2"]) |
|
79 |
||
80 |
def test_annotate(self): |
|
81 |
content = KnitContent([]) |
|
82 |
self.assertEqual(content.annotate(), []) |
|
83 |
||
84 |
content = KnitContent([("origin1", "text1"), ("origin2", "text2")]) |
|
85 |
self.assertEqual(content.annotate(), |
|
86 |
[("origin1", "text1"), ("origin2", "text2")]) |
|
87 |
||
88 |
def test_annotate_iter(self): |
|
89 |
content = KnitContent([]) |
|
90 |
it = content.annotate_iter() |
|
91 |
self.assertRaises(StopIteration, it.next) |
|
92 |
||
93 |
content = KnitContent([("origin1", "text1"), ("origin2", "text2")]) |
|
94 |
it = content.annotate_iter() |
|
95 |
self.assertEqual(it.next(), ("origin1", "text1")) |
|
96 |
self.assertEqual(it.next(), ("origin2", "text2")) |
|
97 |
self.assertRaises(StopIteration, it.next) |
|
98 |
||
99 |
def test_copy(self): |
|
100 |
content = KnitContent([("origin1", "text1"), ("origin2", "text2")]) |
|
101 |
copy = content.copy() |
|
102 |
self.assertIsInstance(copy, KnitContent) |
|
103 |
self.assertEqual(copy.annotate(), |
|
104 |
[("origin1", "text1"), ("origin2", "text2")]) |
|
105 |
||
106 |
def test_line_delta(self): |
|
107 |
content1 = KnitContent([("", "a"), ("", "b")]) |
|
108 |
content2 = KnitContent([("", "a"), ("", "a"), ("", "c")]) |
|
109 |
self.assertEqual(content1.line_delta(content2), |
|
110 |
[(1, 2, 2, [("", "a"), ("", "c")])]) |
|
111 |
||
112 |
def test_line_delta_iter(self): |
|
113 |
content1 = KnitContent([("", "a"), ("", "b")]) |
|
114 |
content2 = KnitContent([("", "a"), ("", "a"), ("", "c")]) |
|
115 |
it = content1.line_delta_iter(content2) |
|
116 |
self.assertEqual(it.next(), (1, 2, 2, [("", "a"), ("", "c")])) |
|
117 |
self.assertRaises(StopIteration, it.next) |
|
118 |
||
2158.3.1
by Dmitry Vasiliev
KnitIndex tests/fixes/optimizations |
119 |
|
120 |
class MockTransport(object): |
|
121 |
||
122 |
def __init__(self, file_lines=None): |
|
123 |
self.file_lines = file_lines |
|
124 |
self.calls = [] |
|
2196.2.3
by John Arbash Meinel
Update tests and code to pass after merging bzr.dev |
125 |
# We have no base directory for the MockTransport
|
126 |
self.base = '' |
|
2158.3.1
by Dmitry Vasiliev
KnitIndex tests/fixes/optimizations |
127 |
|
128 |
def get(self, filename): |
|
129 |
if self.file_lines is None: |
|
130 |
raise NoSuchFile(filename) |
|
131 |
else: |
|
132 |
return StringIO("\n".join(self.file_lines)) |
|
133 |
||
2329.1.1
by John Arbash Meinel
Update _KnitData parser to raise more helpful errors when it detects corruption. |
134 |
def readv(self, relpath, offsets): |
135 |
fp = self.get(relpath) |
|
136 |
for offset, size in offsets: |
|
137 |
fp.seek(offset) |
|
138 |
yield offset, fp.read(size) |
|
139 |
||
2158.3.1
by Dmitry Vasiliev
KnitIndex tests/fixes/optimizations |
140 |
def __getattr__(self, name): |
141 |
def queue_call(*args, **kwargs): |
|
142 |
self.calls.append((name, args, kwargs)) |
|
143 |
return queue_call |
|
144 |
||
145 |
||
2329.1.1
by John Arbash Meinel
Update _KnitData parser to raise more helpful errors when it detects corruption. |
146 |
class LowLevelKnitDataTests(TestCase): |
147 |
||
148 |
def create_gz_content(self, text): |
|
149 |
sio = StringIO() |
|
150 |
gz_file = gzip.GzipFile(mode='wb', fileobj=sio) |
|
151 |
gz_file.write(text) |
|
152 |
gz_file.close() |
|
153 |
return sio.getvalue() |
|
154 |
||
155 |
def test_valid_knit_data(self): |
|
156 |
sha1sum = sha.new('foo\nbar\n').hexdigest() |
|
157 |
gz_txt = self.create_gz_content('version rev-id-1 2 %s\n' |
|
158 |
'foo\n' |
|
159 |
'bar\n' |
|
160 |
'end rev-id-1\n' |
|
161 |
% (sha1sum,)) |
|
162 |
transport = MockTransport([gz_txt]) |
|
163 |
data = _KnitData(transport, 'filename', mode='r') |
|
164 |
records = [('rev-id-1', 0, len(gz_txt))] |
|
165 |
||
166 |
contents = data.read_records(records) |
|
167 |
self.assertEqual({'rev-id-1':(['foo\n', 'bar\n'], sha1sum)}, contents) |
|
168 |
||
169 |
raw_contents = list(data.read_records_iter_raw(records)) |
|
170 |
self.assertEqual([('rev-id-1', gz_txt)], raw_contents) |
|
171 |
||
172 |
def test_not_enough_lines(self): |
|
173 |
sha1sum = sha.new('foo\n').hexdigest() |
|
174 |
# record says 2 lines data says 1
|
|
175 |
gz_txt = self.create_gz_content('version rev-id-1 2 %s\n' |
|
176 |
'foo\n' |
|
177 |
'end rev-id-1\n' |
|
178 |
% (sha1sum,)) |
|
179 |
transport = MockTransport([gz_txt]) |
|
180 |
data = _KnitData(transport, 'filename', mode='r') |
|
181 |
records = [('rev-id-1', 0, len(gz_txt))] |
|
182 |
self.assertRaises(errors.KnitCorrupt, data.read_records, records) |
|
183 |
||
184 |
# read_records_iter_raw won't detect that sort of mismatch/corruption
|
|
185 |
raw_contents = list(data.read_records_iter_raw(records)) |
|
186 |
self.assertEqual([('rev-id-1', gz_txt)], raw_contents) |
|
187 |
||
188 |
def test_too_many_lines(self): |
|
189 |
sha1sum = sha.new('foo\nbar\n').hexdigest() |
|
190 |
# record says 1 lines data says 2
|
|
191 |
gz_txt = self.create_gz_content('version rev-id-1 1 %s\n' |
|
192 |
'foo\n' |
|
193 |
'bar\n' |
|
194 |
'end rev-id-1\n' |
|
195 |
% (sha1sum,)) |
|
196 |
transport = MockTransport([gz_txt]) |
|
197 |
data = _KnitData(transport, 'filename', mode='r') |
|
198 |
records = [('rev-id-1', 0, len(gz_txt))] |
|
199 |
self.assertRaises(errors.KnitCorrupt, data.read_records, records) |
|
200 |
||
201 |
# read_records_iter_raw won't detect that sort of mismatch/corruption
|
|
202 |
raw_contents = list(data.read_records_iter_raw(records)) |
|
203 |
self.assertEqual([('rev-id-1', gz_txt)], raw_contents) |
|
204 |
||
205 |
def test_mismatched_version_id(self): |
|
206 |
sha1sum = sha.new('foo\nbar\n').hexdigest() |
|
207 |
gz_txt = self.create_gz_content('version rev-id-1 2 %s\n' |
|
208 |
'foo\n' |
|
209 |
'bar\n' |
|
210 |
'end rev-id-1\n' |
|
211 |
% (sha1sum,)) |
|
212 |
transport = MockTransport([gz_txt]) |
|
213 |
data = _KnitData(transport, 'filename', mode='r') |
|
214 |
# We are asking for rev-id-2, but the data is rev-id-1
|
|
215 |
records = [('rev-id-2', 0, len(gz_txt))] |
|
216 |
self.assertRaises(errors.KnitCorrupt, data.read_records, records) |
|
217 |
||
218 |
# read_records_iter_raw will notice if we request the wrong version.
|
|
219 |
self.assertRaises(errors.KnitCorrupt, list, |
|
220 |
data.read_records_iter_raw(records)) |
|
221 |
||
222 |
def test_uncompressed_data(self): |
|
223 |
sha1sum = sha.new('foo\nbar\n').hexdigest() |
|
224 |
txt = ('version rev-id-1 2 %s\n' |
|
225 |
'foo\n' |
|
226 |
'bar\n' |
|
227 |
'end rev-id-1\n' |
|
228 |
% (sha1sum,)) |
|
229 |
transport = MockTransport([txt]) |
|
230 |
data = _KnitData(transport, 'filename', mode='r') |
|
231 |
records = [('rev-id-1', 0, len(txt))] |
|
232 |
||
233 |
# We don't have valid gzip data ==> corrupt
|
|
234 |
self.assertRaises(errors.KnitCorrupt, data.read_records, records) |
|
235 |
||
236 |
# read_records_iter_raw will notice the bad data
|
|
237 |
self.assertRaises(errors.KnitCorrupt, list, |
|
238 |
data.read_records_iter_raw(records)) |
|
239 |
||
240 |
def test_corrupted_data(self): |
|
241 |
sha1sum = sha.new('foo\nbar\n').hexdigest() |
|
242 |
gz_txt = self.create_gz_content('version rev-id-1 2 %s\n' |
|
243 |
'foo\n' |
|
244 |
'bar\n' |
|
245 |
'end rev-id-1\n' |
|
246 |
% (sha1sum,)) |
|
247 |
# Change 2 bytes in the middle to \xff
|
|
248 |
gz_txt = gz_txt[:10] + '\xff\xff' + gz_txt[12:] |
|
249 |
transport = MockTransport([gz_txt]) |
|
250 |
data = _KnitData(transport, 'filename', mode='r') |
|
251 |
records = [('rev-id-1', 0, len(gz_txt))] |
|
252 |
||
253 |
self.assertRaises(errors.KnitCorrupt, data.read_records, records) |
|
254 |
||
255 |
# read_records_iter_raw will notice if we request the wrong version.
|
|
256 |
self.assertRaises(errors.KnitCorrupt, list, |
|
257 |
data.read_records_iter_raw(records)) |
|
258 |
||
259 |
||
2158.3.1
by Dmitry Vasiliev
KnitIndex tests/fixes/optimizations |
260 |
class LowLevelKnitIndexTests(TestCase): |
261 |
||
2484.1.1
by John Arbash Meinel
Add an initial function to read knit indexes in pyrex. |
262 |
def get_knit_index(self, *args, **kwargs): |
263 |
orig = knit._load_data |
|
264 |
def reset(): |
|
265 |
knit._load_data = orig |
|
266 |
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 |
267 |
from bzrlib._knit_load_data_py import _load_data_py |
268 |
knit._load_data = _load_data_py |
|
2484.1.1
by John Arbash Meinel
Add an initial function to read knit indexes in pyrex. |
269 |
return _KnitIndex(*args, **kwargs) |
270 |
||
2158.3.1
by Dmitry Vasiliev
KnitIndex tests/fixes/optimizations |
271 |
def test_no_such_file(self): |
272 |
transport = MockTransport() |
|
273 |
||
2484.1.1
by John Arbash Meinel
Add an initial function to read knit indexes in pyrex. |
274 |
self.assertRaises(NoSuchFile, self.get_knit_index, |
275 |
transport, "filename", "r") |
|
276 |
self.assertRaises(NoSuchFile, self.get_knit_index, |
|
277 |
transport, "filename", "w", create=False) |
|
2158.3.1
by Dmitry Vasiliev
KnitIndex tests/fixes/optimizations |
278 |
|
279 |
def test_create_file(self): |
|
280 |
transport = MockTransport() |
|
281 |
||
2484.1.1
by John Arbash Meinel
Add an initial function to read knit indexes in pyrex. |
282 |
index = self.get_knit_index(transport, "filename", "w", |
2158.3.1
by Dmitry Vasiliev
KnitIndex tests/fixes/optimizations |
283 |
file_mode="wb", create=True) |
284 |
self.assertEqual( |
|
285 |
("put_bytes_non_atomic", |
|
286 |
("filename", index.HEADER), {"mode": "wb"}), |
|
287 |
transport.calls.pop(0)) |
|
288 |
||
289 |
def test_delay_create_file(self): |
|
290 |
transport = MockTransport() |
|
291 |
||
2484.1.1
by John Arbash Meinel
Add an initial function to read knit indexes in pyrex. |
292 |
index = self.get_knit_index(transport, "filename", "w", |
2158.3.1
by Dmitry Vasiliev
KnitIndex tests/fixes/optimizations |
293 |
create=True, file_mode="wb", create_parent_dir=True, |
294 |
delay_create=True, dir_mode=0777) |
|
295 |
self.assertEqual([], transport.calls) |
|
296 |
||
297 |
index.add_versions([]) |
|
298 |
name, (filename, f), kwargs = transport.calls.pop(0) |
|
299 |
self.assertEqual("put_file_non_atomic", name) |
|
300 |
self.assertEqual( |
|
301 |
{"dir_mode": 0777, "create_parent_dir": True, "mode": "wb"}, |
|
302 |
kwargs) |
|
303 |
self.assertEqual("filename", filename) |
|
304 |
self.assertEqual(index.HEADER, f.read()) |
|
305 |
||
306 |
index.add_versions([]) |
|
307 |
self.assertEqual(("append_bytes", ("filename", ""), {}), |
|
308 |
transport.calls.pop(0)) |
|
309 |
||
310 |
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 |
311 |
unicode_revision_id = u"version-\N{CYRILLIC CAPITAL LETTER A}" |
312 |
utf8_revision_id = unicode_revision_id.encode('utf-8') |
|
2158.3.1
by Dmitry Vasiliev
KnitIndex tests/fixes/optimizations |
313 |
transport = MockTransport([ |
314 |
_KnitIndex.HEADER, |
|
2249.5.12
by John Arbash Meinel
Change the APIs for VersionedFile, Store, and some of Repository into utf-8 |
315 |
'%s option 0 1 :' % (utf8_revision_id,) |
2158.3.1
by Dmitry Vasiliev
KnitIndex tests/fixes/optimizations |
316 |
])
|
2484.1.1
by John Arbash Meinel
Add an initial function to read knit indexes in pyrex. |
317 |
index = self.get_knit_index(transport, "filename", "r") |
2249.5.12
by John Arbash Meinel
Change the APIs for VersionedFile, Store, and some of Repository into utf-8 |
318 |
# _KnitIndex is a private class, and deals in utf8 revision_ids, not
|
319 |
# Unicode revision_ids.
|
|
320 |
self.assertTrue(index.has_version(utf8_revision_id)) |
|
321 |
self.assertFalse(index.has_version(unicode_revision_id)) |
|
2158.3.1
by Dmitry Vasiliev
KnitIndex tests/fixes/optimizations |
322 |
|
323 |
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 |
324 |
unicode_revision_id = u"version-\N{CYRILLIC CAPITAL LETTER A}" |
325 |
utf8_revision_id = unicode_revision_id.encode('utf-8') |
|
2158.3.1
by Dmitry Vasiliev
KnitIndex tests/fixes/optimizations |
326 |
transport = MockTransport([ |
327 |
_KnitIndex.HEADER, |
|
2249.5.12
by John Arbash Meinel
Change the APIs for VersionedFile, Store, and some of Repository into utf-8 |
328 |
"version option 0 1 .%s :" % (utf8_revision_id,) |
2158.3.1
by Dmitry Vasiliev
KnitIndex tests/fixes/optimizations |
329 |
])
|
2484.1.1
by John Arbash Meinel
Add an initial function to read knit indexes in pyrex. |
330 |
index = self.get_knit_index(transport, "filename", "r") |
2249.5.12
by John Arbash Meinel
Change the APIs for VersionedFile, Store, and some of Repository into utf-8 |
331 |
self.assertEqual([utf8_revision_id], |
2158.3.1
by Dmitry Vasiliev
KnitIndex tests/fixes/optimizations |
332 |
index.get_parents_with_ghosts("version")) |
333 |
||
334 |
def test_read_ignore_corrupted_lines(self): |
|
335 |
transport = MockTransport([ |
|
336 |
_KnitIndex.HEADER, |
|
337 |
"corrupted", |
|
338 |
"corrupted options 0 1 .b .c ", |
|
339 |
"version options 0 1 :"
|
|
340 |
])
|
|
2484.1.1
by John Arbash Meinel
Add an initial function to read knit indexes in pyrex. |
341 |
index = self.get_knit_index(transport, "filename", "r") |
2158.3.1
by Dmitry Vasiliev
KnitIndex tests/fixes/optimizations |
342 |
self.assertEqual(1, index.num_versions()) |
2249.5.12
by John Arbash Meinel
Change the APIs for VersionedFile, Store, and some of Repository into utf-8 |
343 |
self.assertTrue(index.has_version("version")) |
2158.3.1
by Dmitry Vasiliev
KnitIndex tests/fixes/optimizations |
344 |
|
345 |
def test_read_corrupted_header(self): |
|
2196.2.3
by John Arbash Meinel
Update tests and code to pass after merging bzr.dev |
346 |
transport = MockTransport(['not a bzr knit index header\n']) |
2158.3.1
by Dmitry Vasiliev
KnitIndex tests/fixes/optimizations |
347 |
self.assertRaises(KnitHeaderError, |
2484.1.1
by John Arbash Meinel
Add an initial function to read knit indexes in pyrex. |
348 |
self.get_knit_index, transport, "filename", "r") |
2158.3.1
by Dmitry Vasiliev
KnitIndex tests/fixes/optimizations |
349 |
|
350 |
def test_read_duplicate_entries(self): |
|
351 |
transport = MockTransport([ |
|
352 |
_KnitIndex.HEADER, |
|
353 |
"parent options 0 1 :", |
|
354 |
"version options1 0 1 0 :", |
|
355 |
"version options2 1 2 .other :", |
|
356 |
"version options3 3 4 0 .other :"
|
|
357 |
])
|
|
2484.1.1
by John Arbash Meinel
Add an initial function to read knit indexes in pyrex. |
358 |
index = self.get_knit_index(transport, "filename", "r") |
2158.3.1
by Dmitry Vasiliev
KnitIndex tests/fixes/optimizations |
359 |
self.assertEqual(2, index.num_versions()) |
2249.5.12
by John Arbash Meinel
Change the APIs for VersionedFile, Store, and some of Repository into utf-8 |
360 |
self.assertEqual(1, index.lookup("version")) |
361 |
self.assertEqual((3, 4), index.get_position("version")) |
|
362 |
self.assertEqual(["options3"], index.get_options("version")) |
|
363 |
self.assertEqual(["parent", "other"], |
|
364 |
index.get_parents_with_ghosts("version")) |
|
2158.3.1
by Dmitry Vasiliev
KnitIndex tests/fixes/optimizations |
365 |
|
366 |
def test_read_compressed_parents(self): |
|
367 |
transport = MockTransport([ |
|
368 |
_KnitIndex.HEADER, |
|
369 |
"a option 0 1 :", |
|
370 |
"b option 0 1 0 :", |
|
371 |
"c option 0 1 1 0 :", |
|
372 |
])
|
|
2484.1.1
by John Arbash Meinel
Add an initial function to read knit indexes in pyrex. |
373 |
index = self.get_knit_index(transport, "filename", "r") |
2249.5.12
by John Arbash Meinel
Change the APIs for VersionedFile, Store, and some of Repository into utf-8 |
374 |
self.assertEqual(["a"], index.get_parents("b")) |
375 |
self.assertEqual(["b", "a"], index.get_parents("c")) |
|
2158.3.1
by Dmitry Vasiliev
KnitIndex tests/fixes/optimizations |
376 |
|
377 |
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 |
378 |
unicode_revision_id = u"version-\N{CYRILLIC CAPITAL LETTER A}" |
379 |
utf8_revision_id = unicode_revision_id.encode('utf-8') |
|
2158.3.1
by Dmitry Vasiliev
KnitIndex tests/fixes/optimizations |
380 |
transport = MockTransport([ |
381 |
_KnitIndex.HEADER |
|
382 |
])
|
|
2484.1.1
by John Arbash Meinel
Add an initial function to read knit indexes in pyrex. |
383 |
index = self.get_knit_index(transport, "filename", "r") |
2249.5.12
by John Arbash Meinel
Change the APIs for VersionedFile, Store, and some of Repository into utf-8 |
384 |
index.add_version(utf8_revision_id, ["option"], 0, 1, []) |
2158.3.1
by Dmitry Vasiliev
KnitIndex tests/fixes/optimizations |
385 |
self.assertEqual(("append_bytes", ("filename", |
2249.5.12
by John Arbash Meinel
Change the APIs for VersionedFile, Store, and some of Repository into utf-8 |
386 |
"\n%s option 0 1 :" % (utf8_revision_id,)), |
2158.3.1
by Dmitry Vasiliev
KnitIndex tests/fixes/optimizations |
387 |
{}),
|
388 |
transport.calls.pop(0)) |
|
389 |
||
390 |
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 |
391 |
unicode_revision_id = u"version-\N{CYRILLIC CAPITAL LETTER A}" |
392 |
utf8_revision_id = unicode_revision_id.encode('utf-8') |
|
2158.3.1
by Dmitry Vasiliev
KnitIndex tests/fixes/optimizations |
393 |
transport = MockTransport([ |
394 |
_KnitIndex.HEADER |
|
395 |
])
|
|
2484.1.1
by John Arbash Meinel
Add an initial function to read knit indexes in pyrex. |
396 |
index = self.get_knit_index(transport, "filename", "r") |
2249.5.12
by John Arbash Meinel
Change the APIs for VersionedFile, Store, and some of Repository into utf-8 |
397 |
index.add_version("version", ["option"], 0, 1, [utf8_revision_id]) |
2158.3.1
by Dmitry Vasiliev
KnitIndex tests/fixes/optimizations |
398 |
self.assertEqual(("append_bytes", ("filename", |
2249.5.12
by John Arbash Meinel
Change the APIs for VersionedFile, Store, and some of Repository into utf-8 |
399 |
"\nversion option 0 1 .%s :" % (utf8_revision_id,)), |
2158.3.1
by Dmitry Vasiliev
KnitIndex tests/fixes/optimizations |
400 |
{}),
|
401 |
transport.calls.pop(0)) |
|
402 |
||
403 |
def test_get_graph(self): |
|
404 |
transport = MockTransport() |
|
2484.1.1
by John Arbash Meinel
Add an initial function to read knit indexes in pyrex. |
405 |
index = self.get_knit_index(transport, "filename", "w", create=True) |
2158.3.1
by Dmitry Vasiliev
KnitIndex tests/fixes/optimizations |
406 |
self.assertEqual([], index.get_graph()) |
407 |
||
2249.5.12
by John Arbash Meinel
Change the APIs for VersionedFile, Store, and some of Repository into utf-8 |
408 |
index.add_version("a", ["option"], 0, 1, ["b"]) |
409 |
self.assertEqual([("a", ["b"])], index.get_graph()) |
|
2158.3.1
by Dmitry Vasiliev
KnitIndex tests/fixes/optimizations |
410 |
|
2249.5.12
by John Arbash Meinel
Change the APIs for VersionedFile, Store, and some of Repository into utf-8 |
411 |
index.add_version("c", ["option"], 0, 1, ["d"]) |
412 |
self.assertEqual([("a", ["b"]), ("c", ["d"])], |
|
2158.3.1
by Dmitry Vasiliev
KnitIndex tests/fixes/optimizations |
413 |
sorted(index.get_graph())) |
414 |
||
415 |
def test_get_ancestry(self): |
|
416 |
transport = MockTransport([ |
|
417 |
_KnitIndex.HEADER, |
|
418 |
"a option 0 1 :", |
|
419 |
"b option 0 1 0 .e :", |
|
420 |
"c option 0 1 1 0 :", |
|
421 |
"d option 0 1 2 .f :"
|
|
422 |
])
|
|
2484.1.1
by John Arbash Meinel
Add an initial function to read knit indexes in pyrex. |
423 |
index = self.get_knit_index(transport, "filename", "r") |
2158.3.1
by Dmitry Vasiliev
KnitIndex tests/fixes/optimizations |
424 |
|
425 |
self.assertEqual([], index.get_ancestry([])) |
|
2249.5.12
by John Arbash Meinel
Change the APIs for VersionedFile, Store, and some of Repository into utf-8 |
426 |
self.assertEqual(["a"], index.get_ancestry(["a"])) |
427 |
self.assertEqual(["a", "b"], index.get_ancestry(["b"])) |
|
428 |
self.assertEqual(["a", "b", "c"], index.get_ancestry(["c"])) |
|
429 |
self.assertEqual(["a", "b", "c", "d"], index.get_ancestry(["d"])) |
|
430 |
self.assertEqual(["a", "b"], index.get_ancestry(["a", "b"])) |
|
431 |
self.assertEqual(["a", "b", "c"], index.get_ancestry(["a", "c"])) |
|
2158.3.1
by Dmitry Vasiliev
KnitIndex tests/fixes/optimizations |
432 |
|
2249.5.12
by John Arbash Meinel
Change the APIs for VersionedFile, Store, and some of Repository into utf-8 |
433 |
self.assertRaises(RevisionNotPresent, index.get_ancestry, ["e"]) |
2158.3.1
by Dmitry Vasiliev
KnitIndex tests/fixes/optimizations |
434 |
|
435 |
def test_get_ancestry_with_ghosts(self): |
|
436 |
transport = MockTransport([ |
|
437 |
_KnitIndex.HEADER, |
|
438 |
"a option 0 1 :", |
|
439 |
"b option 0 1 0 .e :", |
|
440 |
"c option 0 1 0 .f .g :", |
|
441 |
"d option 0 1 2 .h .j .k :"
|
|
442 |
])
|
|
2484.1.1
by John Arbash Meinel
Add an initial function to read knit indexes in pyrex. |
443 |
index = self.get_knit_index(transport, "filename", "r") |
2158.3.1
by Dmitry Vasiliev
KnitIndex tests/fixes/optimizations |
444 |
|
445 |
self.assertEqual([], index.get_ancestry_with_ghosts([])) |
|
2249.5.12
by John Arbash Meinel
Change the APIs for VersionedFile, Store, and some of Repository into utf-8 |
446 |
self.assertEqual(["a"], index.get_ancestry_with_ghosts(["a"])) |
447 |
self.assertEqual(["a", "e", "b"], |
|
448 |
index.get_ancestry_with_ghosts(["b"])) |
|
449 |
self.assertEqual(["a", "g", "f", "c"], |
|
450 |
index.get_ancestry_with_ghosts(["c"])) |
|
451 |
self.assertEqual(["a", "g", "f", "c", "k", "j", "h", "d"], |
|
452 |
index.get_ancestry_with_ghosts(["d"])) |
|
453 |
self.assertEqual(["a", "e", "b"], |
|
454 |
index.get_ancestry_with_ghosts(["a", "b"])) |
|
455 |
self.assertEqual(["a", "g", "f", "c"], |
|
456 |
index.get_ancestry_with_ghosts(["a", "c"])) |
|
2158.3.1
by Dmitry Vasiliev
KnitIndex tests/fixes/optimizations |
457 |
self.assertEqual( |
2249.5.12
by John Arbash Meinel
Change the APIs for VersionedFile, Store, and some of Repository into utf-8 |
458 |
["a", "g", "f", "c", "e", "b", "k", "j", "h", "d"], |
459 |
index.get_ancestry_with_ghosts(["b", "d"])) |
|
2158.3.1
by Dmitry Vasiliev
KnitIndex tests/fixes/optimizations |
460 |
|
461 |
self.assertRaises(RevisionNotPresent, |
|
2249.5.12
by John Arbash Meinel
Change the APIs for VersionedFile, Store, and some of Repository into utf-8 |
462 |
index.get_ancestry_with_ghosts, ["e"]) |
2158.3.1
by Dmitry Vasiliev
KnitIndex tests/fixes/optimizations |
463 |
|
464 |
def test_num_versions(self): |
|
465 |
transport = MockTransport([ |
|
466 |
_KnitIndex.HEADER |
|
467 |
])
|
|
2484.1.1
by John Arbash Meinel
Add an initial function to read knit indexes in pyrex. |
468 |
index = self.get_knit_index(transport, "filename", "r") |
2158.3.1
by Dmitry Vasiliev
KnitIndex tests/fixes/optimizations |
469 |
|
470 |
self.assertEqual(0, index.num_versions()) |
|
471 |
self.assertEqual(0, len(index)) |
|
472 |
||
2249.5.12
by John Arbash Meinel
Change the APIs for VersionedFile, Store, and some of Repository into utf-8 |
473 |
index.add_version("a", ["option"], 0, 1, []) |
474 |
self.assertEqual(1, index.num_versions()) |
|
475 |
self.assertEqual(1, len(index)) |
|
476 |
||
477 |
index.add_version("a", ["option2"], 1, 2, []) |
|
478 |
self.assertEqual(1, index.num_versions()) |
|
479 |
self.assertEqual(1, len(index)) |
|
480 |
||
481 |
index.add_version("b", ["option"], 0, 1, []) |
|
2158.3.1
by Dmitry Vasiliev
KnitIndex tests/fixes/optimizations |
482 |
self.assertEqual(2, index.num_versions()) |
483 |
self.assertEqual(2, len(index)) |
|
484 |
||
485 |
def test_get_versions(self): |
|
486 |
transport = MockTransport([ |
|
487 |
_KnitIndex.HEADER |
|
488 |
])
|
|
2484.1.1
by John Arbash Meinel
Add an initial function to read knit indexes in pyrex. |
489 |
index = self.get_knit_index(transport, "filename", "r") |
2158.3.1
by Dmitry Vasiliev
KnitIndex tests/fixes/optimizations |
490 |
|
491 |
self.assertEqual([], index.get_versions()) |
|
492 |
||
2249.5.12
by John Arbash Meinel
Change the APIs for VersionedFile, Store, and some of Repository into utf-8 |
493 |
index.add_version("a", ["option"], 0, 1, []) |
494 |
self.assertEqual(["a"], index.get_versions()) |
|
495 |
||
496 |
index.add_version("a", ["option"], 0, 1, []) |
|
497 |
self.assertEqual(["a"], index.get_versions()) |
|
498 |
||
499 |
index.add_version("b", ["option"], 0, 1, []) |
|
500 |
self.assertEqual(["a", "b"], index.get_versions()) |
|
2158.3.1
by Dmitry Vasiliev
KnitIndex tests/fixes/optimizations |
501 |
|
502 |
def test_idx_to_name(self): |
|
503 |
transport = MockTransport([ |
|
504 |
_KnitIndex.HEADER, |
|
505 |
"a option 0 1 :", |
|
506 |
"b option 0 1 :"
|
|
507 |
])
|
|
2484.1.1
by John Arbash Meinel
Add an initial function to read knit indexes in pyrex. |
508 |
index = self.get_knit_index(transport, "filename", "r") |
2158.3.1
by Dmitry Vasiliev
KnitIndex tests/fixes/optimizations |
509 |
|
2249.5.12
by John Arbash Meinel
Change the APIs for VersionedFile, Store, and some of Repository into utf-8 |
510 |
self.assertEqual("a", index.idx_to_name(0)) |
511 |
self.assertEqual("b", index.idx_to_name(1)) |
|
512 |
self.assertEqual("b", index.idx_to_name(-1)) |
|
513 |
self.assertEqual("a", index.idx_to_name(-2)) |
|
2158.3.1
by Dmitry Vasiliev
KnitIndex tests/fixes/optimizations |
514 |
|
515 |
def test_lookup(self): |
|
516 |
transport = MockTransport([ |
|
517 |
_KnitIndex.HEADER, |
|
518 |
"a option 0 1 :", |
|
519 |
"b option 0 1 :"
|
|
520 |
])
|
|
2484.1.1
by John Arbash Meinel
Add an initial function to read knit indexes in pyrex. |
521 |
index = self.get_knit_index(transport, "filename", "r") |
2158.3.1
by Dmitry Vasiliev
KnitIndex tests/fixes/optimizations |
522 |
|
2249.5.12
by John Arbash Meinel
Change the APIs for VersionedFile, Store, and some of Repository into utf-8 |
523 |
self.assertEqual(0, index.lookup("a")) |
524 |
self.assertEqual(1, index.lookup("b")) |
|
2158.3.1
by Dmitry Vasiliev
KnitIndex tests/fixes/optimizations |
525 |
|
526 |
def test_add_version(self): |
|
527 |
transport = MockTransport([ |
|
528 |
_KnitIndex.HEADER |
|
529 |
])
|
|
2484.1.1
by John Arbash Meinel
Add an initial function to read knit indexes in pyrex. |
530 |
index = self.get_knit_index(transport, "filename", "r") |
2158.3.1
by Dmitry Vasiliev
KnitIndex tests/fixes/optimizations |
531 |
|
2249.5.12
by John Arbash Meinel
Change the APIs for VersionedFile, Store, and some of Repository into utf-8 |
532 |
index.add_version("a", ["option"], 0, 1, ["b"]) |
2158.3.1
by Dmitry Vasiliev
KnitIndex tests/fixes/optimizations |
533 |
self.assertEqual(("append_bytes", |
534 |
("filename", "\na option 0 1 .b :"), |
|
535 |
{}), transport.calls.pop(0)) |
|
2249.5.12
by John Arbash Meinel
Change the APIs for VersionedFile, Store, and some of Repository into utf-8 |
536 |
self.assertTrue(index.has_version("a")) |
2158.3.1
by Dmitry Vasiliev
KnitIndex tests/fixes/optimizations |
537 |
self.assertEqual(1, index.num_versions()) |
2249.5.12
by John Arbash Meinel
Change the APIs for VersionedFile, Store, and some of Repository into utf-8 |
538 |
self.assertEqual((0, 1), index.get_position("a")) |
539 |
self.assertEqual(["option"], index.get_options("a")) |
|
540 |
self.assertEqual(["b"], index.get_parents_with_ghosts("a")) |
|
2158.3.1
by Dmitry Vasiliev
KnitIndex tests/fixes/optimizations |
541 |
|
2249.5.12
by John Arbash Meinel
Change the APIs for VersionedFile, Store, and some of Repository into utf-8 |
542 |
index.add_version("a", ["opt"], 1, 2, ["c"]) |
2158.3.1
by Dmitry Vasiliev
KnitIndex tests/fixes/optimizations |
543 |
self.assertEqual(("append_bytes", |
544 |
("filename", "\na opt 1 2 .c :"), |
|
545 |
{}), transport.calls.pop(0)) |
|
2249.5.12
by John Arbash Meinel
Change the APIs for VersionedFile, Store, and some of Repository into utf-8 |
546 |
self.assertTrue(index.has_version("a")) |
2158.3.1
by Dmitry Vasiliev
KnitIndex tests/fixes/optimizations |
547 |
self.assertEqual(1, index.num_versions()) |
2249.5.12
by John Arbash Meinel
Change the APIs for VersionedFile, Store, and some of Repository into utf-8 |
548 |
self.assertEqual((1, 2), index.get_position("a")) |
549 |
self.assertEqual(["opt"], index.get_options("a")) |
|
550 |
self.assertEqual(["c"], index.get_parents_with_ghosts("a")) |
|
2158.3.1
by Dmitry Vasiliev
KnitIndex tests/fixes/optimizations |
551 |
|
2249.5.12
by John Arbash Meinel
Change the APIs for VersionedFile, Store, and some of Repository into utf-8 |
552 |
index.add_version("b", ["option"], 2, 3, ["a"]) |
2158.3.1
by Dmitry Vasiliev
KnitIndex tests/fixes/optimizations |
553 |
self.assertEqual(("append_bytes", |
554 |
("filename", "\nb option 2 3 0 :"), |
|
555 |
{}), transport.calls.pop(0)) |
|
2249.5.12
by John Arbash Meinel
Change the APIs for VersionedFile, Store, and some of Repository into utf-8 |
556 |
self.assertTrue(index.has_version("b")) |
2158.3.1
by Dmitry Vasiliev
KnitIndex tests/fixes/optimizations |
557 |
self.assertEqual(2, index.num_versions()) |
2249.5.12
by John Arbash Meinel
Change the APIs for VersionedFile, Store, and some of Repository into utf-8 |
558 |
self.assertEqual((2, 3), index.get_position("b")) |
559 |
self.assertEqual(["option"], index.get_options("b")) |
|
560 |
self.assertEqual(["a"], index.get_parents_with_ghosts("b")) |
|
2158.3.1
by Dmitry Vasiliev
KnitIndex tests/fixes/optimizations |
561 |
|
562 |
def test_add_versions(self): |
|
563 |
transport = MockTransport([ |
|
564 |
_KnitIndex.HEADER |
|
565 |
])
|
|
2484.1.1
by John Arbash Meinel
Add an initial function to read knit indexes in pyrex. |
566 |
index = self.get_knit_index(transport, "filename", "r") |
2158.3.1
by Dmitry Vasiliev
KnitIndex tests/fixes/optimizations |
567 |
|
568 |
index.add_versions([ |
|
2249.5.12
by John Arbash Meinel
Change the APIs for VersionedFile, Store, and some of Repository into utf-8 |
569 |
("a", ["option"], 0, 1, ["b"]), |
570 |
("a", ["opt"], 1, 2, ["c"]), |
|
571 |
("b", ["option"], 2, 3, ["a"]) |
|
2158.3.1
by Dmitry Vasiliev
KnitIndex tests/fixes/optimizations |
572 |
])
|
573 |
self.assertEqual(("append_bytes", ("filename", |
|
574 |
"\na option 0 1 .b :" |
|
575 |
"\na opt 1 2 .c :" |
|
576 |
"\nb option 2 3 0 :" |
|
577 |
), {}), transport.calls.pop(0)) |
|
2249.5.12
by John Arbash Meinel
Change the APIs for VersionedFile, Store, and some of Repository into utf-8 |
578 |
self.assertTrue(index.has_version("a")) |
579 |
self.assertTrue(index.has_version("b")) |
|
2158.3.1
by Dmitry Vasiliev
KnitIndex tests/fixes/optimizations |
580 |
self.assertEqual(2, index.num_versions()) |
2249.5.12
by John Arbash Meinel
Change the APIs for VersionedFile, Store, and some of Repository into utf-8 |
581 |
self.assertEqual((1, 2), index.get_position("a")) |
582 |
self.assertEqual((2, 3), index.get_position("b")) |
|
583 |
self.assertEqual(["opt"], index.get_options("a")) |
|
584 |
self.assertEqual(["option"], index.get_options("b")) |
|
585 |
self.assertEqual(["c"], index.get_parents_with_ghosts("a")) |
|
586 |
self.assertEqual(["a"], index.get_parents_with_ghosts("b")) |
|
2158.3.1
by Dmitry Vasiliev
KnitIndex tests/fixes/optimizations |
587 |
|
588 |
def test_delay_create_and_add_versions(self): |
|
589 |
transport = MockTransport() |
|
590 |
||
2484.1.1
by John Arbash Meinel
Add an initial function to read knit indexes in pyrex. |
591 |
index = self.get_knit_index(transport, "filename", "w", |
2158.3.1
by Dmitry Vasiliev
KnitIndex tests/fixes/optimizations |
592 |
create=True, file_mode="wb", create_parent_dir=True, |
593 |
delay_create=True, dir_mode=0777) |
|
594 |
self.assertEqual([], transport.calls) |
|
595 |
||
596 |
index.add_versions([ |
|
2249.5.12
by John Arbash Meinel
Change the APIs for VersionedFile, Store, and some of Repository into utf-8 |
597 |
("a", ["option"], 0, 1, ["b"]), |
598 |
("a", ["opt"], 1, 2, ["c"]), |
|
599 |
("b", ["option"], 2, 3, ["a"]) |
|
2158.3.1
by Dmitry Vasiliev
KnitIndex tests/fixes/optimizations |
600 |
])
|
601 |
name, (filename, f), kwargs = transport.calls.pop(0) |
|
602 |
self.assertEqual("put_file_non_atomic", name) |
|
603 |
self.assertEqual( |
|
604 |
{"dir_mode": 0777, "create_parent_dir": True, "mode": "wb"}, |
|
605 |
kwargs) |
|
606 |
self.assertEqual("filename", filename) |
|
607 |
self.assertEqual( |
|
608 |
index.HEADER + |
|
609 |
"\na option 0 1 .b :" |
|
610 |
"\na opt 1 2 .c :" |
|
611 |
"\nb option 2 3 0 :", |
|
612 |
f.read()) |
|
613 |
||
614 |
def test_has_version(self): |
|
615 |
transport = MockTransport([ |
|
616 |
_KnitIndex.HEADER, |
|
617 |
"a option 0 1 :"
|
|
618 |
])
|
|
2484.1.1
by John Arbash Meinel
Add an initial function to read knit indexes in pyrex. |
619 |
index = self.get_knit_index(transport, "filename", "r") |
2158.3.1
by Dmitry Vasiliev
KnitIndex tests/fixes/optimizations |
620 |
|
2249.5.12
by John Arbash Meinel
Change the APIs for VersionedFile, Store, and some of Repository into utf-8 |
621 |
self.assertTrue(index.has_version("a")) |
622 |
self.assertFalse(index.has_version("b")) |
|
2158.3.1
by Dmitry Vasiliev
KnitIndex tests/fixes/optimizations |
623 |
|
624 |
def test_get_position(self): |
|
625 |
transport = MockTransport([ |
|
626 |
_KnitIndex.HEADER, |
|
627 |
"a option 0 1 :", |
|
628 |
"b option 1 2 :"
|
|
629 |
])
|
|
2484.1.1
by John Arbash Meinel
Add an initial function to read knit indexes in pyrex. |
630 |
index = self.get_knit_index(transport, "filename", "r") |
2158.3.1
by Dmitry Vasiliev
KnitIndex tests/fixes/optimizations |
631 |
|
2249.5.12
by John Arbash Meinel
Change the APIs for VersionedFile, Store, and some of Repository into utf-8 |
632 |
self.assertEqual((0, 1), index.get_position("a")) |
633 |
self.assertEqual((1, 2), index.get_position("b")) |
|
2158.3.1
by Dmitry Vasiliev
KnitIndex tests/fixes/optimizations |
634 |
|
635 |
def test_get_method(self): |
|
636 |
transport = MockTransport([ |
|
637 |
_KnitIndex.HEADER, |
|
638 |
"a fulltext,unknown 0 1 :", |
|
639 |
"b unknown,line-delta 1 2 :", |
|
640 |
"c bad 3 4 :"
|
|
641 |
])
|
|
2484.1.1
by John Arbash Meinel
Add an initial function to read knit indexes in pyrex. |
642 |
index = self.get_knit_index(transport, "filename", "r") |
2158.3.1
by Dmitry Vasiliev
KnitIndex tests/fixes/optimizations |
643 |
|
2249.5.12
by John Arbash Meinel
Change the APIs for VersionedFile, Store, and some of Repository into utf-8 |
644 |
self.assertEqual("fulltext", index.get_method("a")) |
645 |
self.assertEqual("line-delta", index.get_method("b")) |
|
646 |
self.assertRaises(errors.KnitIndexUnknownMethod, index.get_method, "c") |
|
2158.3.1
by Dmitry Vasiliev
KnitIndex tests/fixes/optimizations |
647 |
|
648 |
def test_get_options(self): |
|
649 |
transport = MockTransport([ |
|
650 |
_KnitIndex.HEADER, |
|
651 |
"a opt1 0 1 :", |
|
652 |
"b opt2,opt3 1 2 :"
|
|
653 |
])
|
|
2484.1.1
by John Arbash Meinel
Add an initial function to read knit indexes in pyrex. |
654 |
index = self.get_knit_index(transport, "filename", "r") |
2158.3.1
by Dmitry Vasiliev
KnitIndex tests/fixes/optimizations |
655 |
|
2249.5.12
by John Arbash Meinel
Change the APIs for VersionedFile, Store, and some of Repository into utf-8 |
656 |
self.assertEqual(["opt1"], index.get_options("a")) |
657 |
self.assertEqual(["opt2", "opt3"], index.get_options("b")) |
|
2158.3.1
by Dmitry Vasiliev
KnitIndex tests/fixes/optimizations |
658 |
|
659 |
def test_get_parents(self): |
|
660 |
transport = MockTransport([ |
|
661 |
_KnitIndex.HEADER, |
|
662 |
"a option 0 1 :", |
|
663 |
"b option 1 2 0 .c :", |
|
664 |
"c option 1 2 1 0 .e :"
|
|
665 |
])
|
|
2484.1.1
by John Arbash Meinel
Add an initial function to read knit indexes in pyrex. |
666 |
index = self.get_knit_index(transport, "filename", "r") |
2158.3.1
by Dmitry Vasiliev
KnitIndex tests/fixes/optimizations |
667 |
|
2249.5.12
by John Arbash Meinel
Change the APIs for VersionedFile, Store, and some of Repository into utf-8 |
668 |
self.assertEqual([], index.get_parents("a")) |
669 |
self.assertEqual(["a", "c"], index.get_parents("b")) |
|
670 |
self.assertEqual(["b", "a"], index.get_parents("c")) |
|
2158.3.1
by Dmitry Vasiliev
KnitIndex tests/fixes/optimizations |
671 |
|
672 |
def test_get_parents_with_ghosts(self): |
|
673 |
transport = MockTransport([ |
|
674 |
_KnitIndex.HEADER, |
|
675 |
"a option 0 1 :", |
|
676 |
"b option 1 2 0 .c :", |
|
677 |
"c option 1 2 1 0 .e :"
|
|
678 |
])
|
|
2484.1.1
by John Arbash Meinel
Add an initial function to read knit indexes in pyrex. |
679 |
index = self.get_knit_index(transport, "filename", "r") |
2158.3.1
by Dmitry Vasiliev
KnitIndex tests/fixes/optimizations |
680 |
|
2249.5.12
by John Arbash Meinel
Change the APIs for VersionedFile, Store, and some of Repository into utf-8 |
681 |
self.assertEqual([], index.get_parents_with_ghosts("a")) |
682 |
self.assertEqual(["a", "c"], index.get_parents_with_ghosts("b")) |
|
683 |
self.assertEqual(["b", "a", "e"], |
|
684 |
index.get_parents_with_ghosts("c")) |
|
2158.3.1
by Dmitry Vasiliev
KnitIndex tests/fixes/optimizations |
685 |
|
686 |
def test_check_versions_present(self): |
|
687 |
transport = MockTransport([ |
|
688 |
_KnitIndex.HEADER, |
|
689 |
"a option 0 1 :", |
|
690 |
"b option 0 1 :"
|
|
691 |
])
|
|
2484.1.1
by John Arbash Meinel
Add an initial function to read knit indexes in pyrex. |
692 |
index = self.get_knit_index(transport, "filename", "r") |
2158.3.1
by Dmitry Vasiliev
KnitIndex tests/fixes/optimizations |
693 |
|
694 |
check = index.check_versions_present |
|
695 |
||
696 |
check([]) |
|
2249.5.12
by John Arbash Meinel
Change the APIs for VersionedFile, Store, and some of Repository into utf-8 |
697 |
check(["a"]) |
698 |
check(["b"]) |
|
699 |
check(["a", "b"]) |
|
700 |
self.assertRaises(RevisionNotPresent, check, ["c"]) |
|
701 |
self.assertRaises(RevisionNotPresent, check, ["a", "b", "c"]) |
|
2158.3.1
by Dmitry Vasiliev
KnitIndex tests/fixes/optimizations |
702 |
|
2484.1.13
by John Arbash Meinel
Add a test that KnitCorrupt is raised when parent strings are invalid. |
703 |
def test_impossible_parent(self): |
704 |
"""Test we get KnitCorrupt if the parent couldn't possibly exist."""
|
|
705 |
transport = MockTransport([ |
|
706 |
_KnitIndex.HEADER, |
|
707 |
"a option 0 1 :", |
|
708 |
"b option 0 1 4 :" # We don't have a 4th record |
|
709 |
])
|
|
2484.1.17
by John Arbash Meinel
Workaround for Pyrex <0.9.5 and python >=2.5 incompatibilities. |
710 |
try: |
711 |
self.assertRaises(errors.KnitCorrupt, |
|
712 |
self.get_knit_index, transport, 'filename', 'r') |
|
713 |
except TypeError, e: |
|
714 |
if (str(e) == ('exceptions must be strings, classes, or instances,' |
|
715 |
' not exceptions.IndexError') |
|
716 |
and sys.version_info[0:2] >= (2,5)): |
|
717 |
self.knownFailure('Pyrex <0.9.5 fails with TypeError when' |
|
718 |
' raising new style exceptions with python'
|
|
719 |
' >=2.5') |
|
2484.1.19
by John Arbash Meinel
Don't suppress the TypeError if it doesn't match our requirements. |
720 |
else: |
721 |
raise
|
|
2484.1.13
by John Arbash Meinel
Add a test that KnitCorrupt is raised when parent strings are invalid. |
722 |
|
723 |
def test_corrupted_parent(self): |
|
724 |
transport = MockTransport([ |
|
725 |
_KnitIndex.HEADER, |
|
726 |
"a option 0 1 :", |
|
727 |
"b option 0 1 :", |
|
728 |
"c option 0 1 1v :", # Can't have a parent of '1v' |
|
729 |
])
|
|
2484.1.17
by John Arbash Meinel
Workaround for Pyrex <0.9.5 and python >=2.5 incompatibilities. |
730 |
try: |
731 |
self.assertRaises(errors.KnitCorrupt, |
|
732 |
self.get_knit_index, transport, 'filename', 'r') |
|
733 |
except TypeError, e: |
|
734 |
if (str(e) == ('exceptions must be strings, classes, or instances,' |
|
735 |
' not exceptions.ValueError') |
|
736 |
and sys.version_info[0:2] >= (2,5)): |
|
737 |
self.knownFailure('Pyrex <0.9.5 fails with TypeError when' |
|
738 |
' raising new style exceptions with python'
|
|
739 |
' >=2.5') |
|
2484.1.19
by John Arbash Meinel
Don't suppress the TypeError if it doesn't match our requirements. |
740 |
else: |
741 |
raise
|
|
2484.1.13
by John Arbash Meinel
Add a test that KnitCorrupt is raised when parent strings are invalid. |
742 |
|
743 |
def test_corrupted_parent_in_list(self): |
|
744 |
transport = MockTransport([ |
|
745 |
_KnitIndex.HEADER, |
|
746 |
"a option 0 1 :", |
|
747 |
"b option 0 1 :", |
|
2484.1.17
by John Arbash Meinel
Workaround for Pyrex <0.9.5 and python >=2.5 incompatibilities. |
748 |
"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. |
749 |
])
|
2484.1.17
by John Arbash Meinel
Workaround for Pyrex <0.9.5 and python >=2.5 incompatibilities. |
750 |
try: |
751 |
self.assertRaises(errors.KnitCorrupt, |
|
752 |
self.get_knit_index, transport, 'filename', 'r') |
|
753 |
except TypeError, e: |
|
754 |
if (str(e) == ('exceptions must be strings, classes, or instances,' |
|
755 |
' not exceptions.ValueError') |
|
756 |
and sys.version_info[0:2] >= (2,5)): |
|
757 |
self.knownFailure('Pyrex <0.9.5 fails with TypeError when' |
|
758 |
' raising new style exceptions with python'
|
|
759 |
' >=2.5') |
|
2484.1.19
by John Arbash Meinel
Don't suppress the TypeError if it doesn't match our requirements. |
760 |
else: |
761 |
raise
|
|
2484.1.13
by John Arbash Meinel
Add a test that KnitCorrupt is raised when parent strings are invalid. |
762 |
|
2484.1.18
by John Arbash Meinel
Test that we properly verify the size and position strings. |
763 |
def test_invalid_position(self): |
764 |
transport = MockTransport([ |
|
765 |
_KnitIndex.HEADER, |
|
766 |
"a option 1v 1 :", |
|
767 |
])
|
|
768 |
try: |
|
769 |
self.assertRaises(errors.KnitCorrupt, |
|
770 |
self.get_knit_index, transport, 'filename', 'r') |
|
771 |
except TypeError, e: |
|
772 |
if (str(e) == ('exceptions must be strings, classes, or instances,' |
|
773 |
' not exceptions.ValueError') |
|
774 |
and sys.version_info[0:2] >= (2,5)): |
|
775 |
self.knownFailure('Pyrex <0.9.5 fails with TypeError when' |
|
776 |
' raising new style exceptions with python'
|
|
777 |
' >=2.5') |
|
2484.1.19
by John Arbash Meinel
Don't suppress the TypeError if it doesn't match our requirements. |
778 |
else: |
779 |
raise
|
|
2484.1.18
by John Arbash Meinel
Test that we properly verify the size and position strings. |
780 |
|
781 |
def test_invalid_size(self): |
|
782 |
transport = MockTransport([ |
|
783 |
_KnitIndex.HEADER, |
|
784 |
"a option 1 1v :", |
|
785 |
])
|
|
786 |
try: |
|
787 |
self.assertRaises(errors.KnitCorrupt, |
|
788 |
self.get_knit_index, transport, 'filename', 'r') |
|
789 |
except TypeError, e: |
|
790 |
if (str(e) == ('exceptions must be strings, classes, or instances,' |
|
791 |
' not exceptions.ValueError') |
|
792 |
and sys.version_info[0:2] >= (2,5)): |
|
793 |
self.knownFailure('Pyrex <0.9.5 fails with TypeError when' |
|
794 |
' raising new style exceptions with python'
|
|
795 |
' >=2.5') |
|
2484.1.19
by John Arbash Meinel
Don't suppress the TypeError if it doesn't match our requirements. |
796 |
else: |
797 |
raise
|
|
2484.1.18
by John Arbash Meinel
Test that we properly verify the size and position strings. |
798 |
|
2484.1.24
by John Arbash Meinel
Add direct tests of how we handle incomplete/'broken' lines |
799 |
def test_short_line(self): |
800 |
transport = MockTransport([ |
|
801 |
_KnitIndex.HEADER, |
|
802 |
"a option 0 10 :", |
|
803 |
"b option 10 10 0", # This line isn't terminated, ignored |
|
804 |
])
|
|
805 |
index = self.get_knit_index(transport, "filename", "r") |
|
806 |
self.assertEqual(['a'], index.get_versions()) |
|
807 |
||
808 |
def test_skip_incomplete_record(self): |
|
809 |
# A line with bogus data should just be skipped
|
|
810 |
transport = MockTransport([ |
|
811 |
_KnitIndex.HEADER, |
|
812 |
"a option 0 10 :", |
|
813 |
"b option 10 10 0", # This line isn't terminated, ignored |
|
814 |
"c option 20 10 0 :", # Properly terminated, and starts with '\n' |
|
815 |
])
|
|
816 |
index = self.get_knit_index(transport, "filename", "r") |
|
817 |
self.assertEqual(['a', 'c'], index.get_versions()) |
|
818 |
||
819 |
def test_trailing_characters(self): |
|
820 |
# A line with bogus data should just be skipped
|
|
821 |
transport = MockTransport([ |
|
822 |
_KnitIndex.HEADER, |
|
823 |
"a option 0 10 :", |
|
824 |
"b option 10 10 0 :a", # This line has extra trailing characters |
|
825 |
"c option 20 10 0 :", # Properly terminated, and starts with '\n' |
|
826 |
])
|
|
827 |
index = self.get_knit_index(transport, "filename", "r") |
|
828 |
self.assertEqual(['a', 'c'], index.get_versions()) |
|
829 |
||
2158.3.1
by Dmitry Vasiliev
KnitIndex tests/fixes/optimizations |
830 |
|
2484.1.1
by John Arbash Meinel
Add an initial function to read knit indexes in pyrex. |
831 |
class LowLevelKnitIndexTests_c(LowLevelKnitIndexTests): |
832 |
||
833 |
_test_needs_features = [CompiledKnitFeature] |
|
834 |
||
835 |
def get_knit_index(self, *args, **kwargs): |
|
836 |
orig = knit._load_data |
|
837 |
def reset(): |
|
838 |
knit._load_data = orig |
|
839 |
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 |
840 |
from bzrlib._knit_load_data_c import _load_data_c |
841 |
knit._load_data = _load_data_c |
|
2484.1.1
by John Arbash Meinel
Add an initial function to read knit indexes in pyrex. |
842 |
return _KnitIndex(*args, **kwargs) |
843 |
||
844 |
||
845 |
||
1684.3.3
by Robert Collins
Add a special cased weaves to knit converter. |
846 |
class KnitTests(TestCaseWithTransport): |
847 |
"""Class containing knit test helper routines."""
|
|
1563.2.16
by Robert Collins
Change WeaveStore into VersionedFileStore and make its versoined file class parameterisable. |
848 |
|
1946.2.1
by John Arbash Meinel
2 changes to knits. Delay creating the .knit or .kndx file until we have actually tried to write data. Because of this, we must allow the Knit to create the prefix directories |
849 |
def make_test_knit(self, annotate=False, delay_create=False): |
1563.2.16
by Robert Collins
Change WeaveStore into VersionedFileStore and make its versoined file class parameterisable. |
850 |
if not annotate: |
851 |
factory = KnitPlainFactory() |
|
852 |
else: |
|
853 |
factory = None |
|
1946.2.1
by John Arbash Meinel
2 changes to knits. Delay creating the .knit or .kndx file until we have actually tried to write data. Because of this, we must allow the Knit to create the prefix directories |
854 |
return KnitVersionedFile('test', get_transport('.'), access_mode='w', |
855 |
factory=factory, create=True, |
|
856 |
delay_create=delay_create) |
|
1563.2.4
by Robert Collins
First cut at including the knit implementation of versioned_file. |
857 |
|
1684.3.3
by Robert Collins
Add a special cased weaves to knit converter. |
858 |
|
859 |
class BasicKnitTests(KnitTests): |
|
860 |
||
861 |
def add_stock_one_and_one_a(self, k): |
|
862 |
k.add_lines('text-1', [], split_lines(TEXT_1)) |
|
863 |
k.add_lines('text-1a', ['text-1'], split_lines(TEXT_1A)) |
|
864 |
||
865 |
def test_knit_constructor(self): |
|
866 |
"""Construct empty k"""
|
|
867 |
self.make_test_knit() |
|
868 |
||
1563.2.4
by Robert Collins
First cut at including the knit implementation of versioned_file. |
869 |
def test_knit_add(self): |
870 |
"""Store one text in knit and retrieve"""
|
|
1563.2.16
by Robert Collins
Change WeaveStore into VersionedFileStore and make its versoined file class parameterisable. |
871 |
k = self.make_test_knit() |
1563.2.4
by Robert Collins
First cut at including the knit implementation of versioned_file. |
872 |
k.add_lines('text-1', [], split_lines(TEXT_1)) |
873 |
self.assertTrue(k.has_version('text-1')) |
|
874 |
self.assertEqualDiff(''.join(k.get_lines('text-1')), TEXT_1) |
|
875 |
||
876 |
def test_knit_reload(self): |
|
1641.1.2
by Robert Collins
Change knit index files to be robust in the presence of partial writes. |
877 |
# test that the content in a reloaded knit is correct
|
1563.2.16
by Robert Collins
Change WeaveStore into VersionedFileStore and make its versoined file class parameterisable. |
878 |
k = self.make_test_knit() |
1563.2.4
by Robert Collins
First cut at including the knit implementation of versioned_file. |
879 |
k.add_lines('text-1', [], split_lines(TEXT_1)) |
880 |
del k |
|
1685.1.39
by John Arbash Meinel
Updating test_knit to not instantiate a LocalTransport directly. |
881 |
k2 = KnitVersionedFile('test', get_transport('.'), access_mode='r', factory=KnitPlainFactory(), create=True) |
1563.2.4
by Robert Collins
First cut at including the knit implementation of versioned_file. |
882 |
self.assertTrue(k2.has_version('text-1')) |
883 |
self.assertEqualDiff(''.join(k2.get_lines('text-1')), TEXT_1) |
|
884 |
||
885 |
def test_knit_several(self): |
|
886 |
"""Store several texts in a knit"""
|
|
1563.2.16
by Robert Collins
Change WeaveStore into VersionedFileStore and make its versoined file class parameterisable. |
887 |
k = self.make_test_knit() |
1563.2.4
by Robert Collins
First cut at including the knit implementation of versioned_file. |
888 |
k.add_lines('text-1', [], split_lines(TEXT_1)) |
889 |
k.add_lines('text-2', [], split_lines(TEXT_2)) |
|
890 |
self.assertEqualDiff(''.join(k.get_lines('text-1')), TEXT_1) |
|
891 |
self.assertEqualDiff(''.join(k.get_lines('text-2')), TEXT_2) |
|
892 |
||
893 |
def test_repeated_add(self): |
|
894 |
"""Knit traps attempt to replace existing version"""
|
|
1563.2.16
by Robert Collins
Change WeaveStore into VersionedFileStore and make its versoined file class parameterisable. |
895 |
k = self.make_test_knit() |
1563.2.4
by Robert Collins
First cut at including the knit implementation of versioned_file. |
896 |
k.add_lines('text-1', [], split_lines(TEXT_1)) |
897 |
self.assertRaises(RevisionAlreadyPresent, |
|
898 |
k.add_lines, |
|
899 |
'text-1', [], split_lines(TEXT_1)) |
|
900 |
||
901 |
def test_empty(self): |
|
1563.2.16
by Robert Collins
Change WeaveStore into VersionedFileStore and make its versoined file class parameterisable. |
902 |
k = self.make_test_knit(True) |
1563.2.4
by Robert Collins
First cut at including the knit implementation of versioned_file. |
903 |
k.add_lines('text-1', [], []) |
904 |
self.assertEquals(k.get_lines('text-1'), []) |
|
905 |
||
906 |
def test_incomplete(self): |
|
907 |
"""Test if texts without a ending line-end can be inserted and
|
|
908 |
extracted."""
|
|
1685.1.39
by John Arbash Meinel
Updating test_knit to not instantiate a LocalTransport directly. |
909 |
k = KnitVersionedFile('test', get_transport('.'), delta=False, create=True) |
1563.2.4
by Robert Collins
First cut at including the knit implementation of versioned_file. |
910 |
k.add_lines('text-1', [], ['a\n', 'b' ]) |
911 |
k.add_lines('text-2', ['text-1'], ['a\rb\n', 'b\n']) |
|
1666.1.6
by Robert Collins
Make knit the default format. |
912 |
# reopening ensures maximum room for confusion
|
1685.1.39
by John Arbash Meinel
Updating test_knit to not instantiate a LocalTransport directly. |
913 |
k = KnitVersionedFile('test', get_transport('.'), delta=False, create=True) |
1563.2.4
by Robert Collins
First cut at including the knit implementation of versioned_file. |
914 |
self.assertEquals(k.get_lines('text-1'), ['a\n', 'b' ]) |
915 |
self.assertEquals(k.get_lines('text-2'), ['a\rb\n', 'b\n']) |
|
916 |
||
917 |
def test_delta(self): |
|
918 |
"""Expression of knit delta as lines"""
|
|
1563.2.16
by Robert Collins
Change WeaveStore into VersionedFileStore and make its versoined file class parameterisable. |
919 |
k = self.make_test_knit() |
2520.4.41
by Aaron Bentley
Accelerate mpdiff generation |
920 |
KnitContent
|
1563.2.4
by Robert Collins
First cut at including the knit implementation of versioned_file. |
921 |
td = list(line_delta(TEXT_1.splitlines(True), |
922 |
TEXT_1A.splitlines(True))) |
|
923 |
self.assertEqualDiff(''.join(td), delta_1_1a) |
|
924 |
out = apply_line_delta(TEXT_1.splitlines(True), td) |
|
925 |
self.assertEqualDiff(''.join(out), TEXT_1A) |
|
926 |
||
2520.4.47
by Aaron Bentley
Fix get_line_delta_blocks with eol |
927 |
def assertDerivedBlocksEqual(self, source, target, noeol=False): |
2520.4.41
by Aaron Bentley
Accelerate mpdiff generation |
928 |
"""Assert that the derived matching blocks match real output"""
|
929 |
source_lines = source.splitlines(True) |
|
930 |
target_lines = target.splitlines(True) |
|
2520.4.47
by Aaron Bentley
Fix get_line_delta_blocks with eol |
931 |
def nl(line): |
932 |
if noeol and not line.endswith('\n'): |
|
933 |
return line + '\n' |
|
934 |
else: |
|
935 |
return line |
|
936 |
source_content = KnitContent([(None, nl(l)) for l in source_lines]) |
|
937 |
target_content = KnitContent([(None, nl(l)) for l in target_lines]) |
|
2520.4.41
by Aaron Bentley
Accelerate mpdiff generation |
938 |
line_delta = source_content.line_delta(target_content) |
2520.4.47
by Aaron Bentley
Fix get_line_delta_blocks with eol |
939 |
delta_blocks = list(KnitContent.get_line_delta_blocks(line_delta, |
940 |
source_lines, target_lines)) |
|
2520.4.41
by Aaron Bentley
Accelerate mpdiff generation |
941 |
matcher = KnitSequenceMatcher(None, source_lines, target_lines) |
2520.4.47
by Aaron Bentley
Fix get_line_delta_blocks with eol |
942 |
matcher_blocks = list(list(matcher.get_matching_blocks())) |
943 |
self.assertEqual(matcher_blocks, delta_blocks) |
|
2520.4.41
by Aaron Bentley
Accelerate mpdiff generation |
944 |
|
945 |
def test_get_line_delta_blocks(self): |
|
946 |
self.assertDerivedBlocksEqual('a\nb\nc\n', 'q\nc\n') |
|
947 |
self.assertDerivedBlocksEqual(TEXT_1, TEXT_1) |
|
948 |
self.assertDerivedBlocksEqual(TEXT_1, TEXT_1A) |
|
949 |
self.assertDerivedBlocksEqual(TEXT_1, TEXT_1B) |
|
950 |
self.assertDerivedBlocksEqual(TEXT_1B, TEXT_1A) |
|
951 |
self.assertDerivedBlocksEqual(TEXT_1A, TEXT_1B) |
|
952 |
self.assertDerivedBlocksEqual(TEXT_1A, '') |
|
953 |
self.assertDerivedBlocksEqual('', TEXT_1A) |
|
954 |
self.assertDerivedBlocksEqual('', '') |
|
2520.4.47
by Aaron Bentley
Fix get_line_delta_blocks with eol |
955 |
self.assertDerivedBlocksEqual('a\nb\nc', 'a\nb\nc\nd') |
956 |
||
957 |
def test_get_line_delta_blocks_noeol(self): |
|
2520.4.48
by Aaron Bentley
Support getting blocks from knit deltas with no final EOL |
958 |
"""Handle historical knit deltas safely
|
959 |
||
960 |
Some existing knit deltas don't consider the last line to differ
|
|
961 |
when the only difference whether it has a final newline.
|
|
962 |
||
963 |
New knit deltas appear to always consider the last line to differ
|
|
964 |
in this case.
|
|
965 |
"""
|
|
2520.4.47
by Aaron Bentley
Fix get_line_delta_blocks with eol |
966 |
self.assertDerivedBlocksEqual('a\nb\nc', 'a\nb\nc\nd\n', noeol=True) |
967 |
self.assertDerivedBlocksEqual('a\nb\nc\nd\n', 'a\nb\nc', noeol=True) |
|
2520.4.48
by Aaron Bentley
Support getting blocks from knit deltas with no final EOL |
968 |
self.assertDerivedBlocksEqual('a\nb\nc\n', 'a\nb\nc', noeol=True) |
969 |
self.assertDerivedBlocksEqual('a\nb\nc', 'a\nb\nc\n', noeol=True) |
|
2520.4.41
by Aaron Bentley
Accelerate mpdiff generation |
970 |
|
1563.2.4
by Robert Collins
First cut at including the knit implementation of versioned_file. |
971 |
def test_add_with_parents(self): |
972 |
"""Store in knit with parents"""
|
|
1563.2.16
by Robert Collins
Change WeaveStore into VersionedFileStore and make its versoined file class parameterisable. |
973 |
k = self.make_test_knit() |
1563.2.4
by Robert Collins
First cut at including the knit implementation of versioned_file. |
974 |
self.add_stock_one_and_one_a(k) |
975 |
self.assertEquals(k.get_parents('text-1'), []) |
|
976 |
self.assertEquals(k.get_parents('text-1a'), ['text-1']) |
|
977 |
||
978 |
def test_ancestry(self): |
|
979 |
"""Store in knit with parents"""
|
|
1563.2.16
by Robert Collins
Change WeaveStore into VersionedFileStore and make its versoined file class parameterisable. |
980 |
k = self.make_test_knit() |
1563.2.4
by Robert Collins
First cut at including the knit implementation of versioned_file. |
981 |
self.add_stock_one_and_one_a(k) |
982 |
self.assertEquals(set(k.get_ancestry(['text-1a'])), set(['text-1a', 'text-1'])) |
|
983 |
||
984 |
def test_add_delta(self): |
|
985 |
"""Store in knit with parents"""
|
|
1685.1.39
by John Arbash Meinel
Updating test_knit to not instantiate a LocalTransport directly. |
986 |
k = KnitVersionedFile('test', get_transport('.'), factory=KnitPlainFactory(), |
1563.2.25
by Robert Collins
Merge in upstream. |
987 |
delta=True, create=True) |
1563.2.4
by Robert Collins
First cut at including the knit implementation of versioned_file. |
988 |
self.add_stock_one_and_one_a(k) |
1596.2.7
by Robert Collins
Remove the requirement for reannotation in knit joins. |
989 |
k.clear_cache() |
1563.2.4
by Robert Collins
First cut at including the knit implementation of versioned_file. |
990 |
self.assertEqualDiff(''.join(k.get_lines('text-1a')), TEXT_1A) |
991 |
||
992 |
def test_annotate(self): |
|
993 |
"""Annotations"""
|
|
1685.1.39
by John Arbash Meinel
Updating test_knit to not instantiate a LocalTransport directly. |
994 |
k = KnitVersionedFile('knit', get_transport('.'), factory=KnitAnnotateFactory(), |
1563.2.25
by Robert Collins
Merge in upstream. |
995 |
delta=True, create=True) |
1563.2.4
by Robert Collins
First cut at including the knit implementation of versioned_file. |
996 |
self.insert_and_test_small_annotate(k) |
997 |
||
998 |
def insert_and_test_small_annotate(self, k): |
|
999 |
"""test annotation with k works correctly."""
|
|
1000 |
k.add_lines('text-1', [], ['a\n', 'b\n']) |
|
1001 |
k.add_lines('text-2', ['text-1'], ['a\n', 'c\n']) |
|
1002 |
||
1003 |
origins = k.annotate('text-2') |
|
1004 |
self.assertEquals(origins[0], ('text-1', 'a\n')) |
|
1005 |
self.assertEquals(origins[1], ('text-2', 'c\n')) |
|
1006 |
||
1007 |
def test_annotate_fulltext(self): |
|
1008 |
"""Annotations"""
|
|
1685.1.39
by John Arbash Meinel
Updating test_knit to not instantiate a LocalTransport directly. |
1009 |
k = KnitVersionedFile('knit', get_transport('.'), factory=KnitAnnotateFactory(), |
1563.2.25
by Robert Collins
Merge in upstream. |
1010 |
delta=False, create=True) |
1563.2.4
by Robert Collins
First cut at including the knit implementation of versioned_file. |
1011 |
self.insert_and_test_small_annotate(k) |
1012 |
||
1013 |
def test_annotate_merge_1(self): |
|
1563.2.16
by Robert Collins
Change WeaveStore into VersionedFileStore and make its versoined file class parameterisable. |
1014 |
k = self.make_test_knit(True) |
1563.2.4
by Robert Collins
First cut at including the knit implementation of versioned_file. |
1015 |
k.add_lines('text-a1', [], ['a\n', 'b\n']) |
1016 |
k.add_lines('text-a2', [], ['d\n', 'c\n']) |
|
1017 |
k.add_lines('text-am', ['text-a1', 'text-a2'], ['d\n', 'b\n']) |
|
1018 |
origins = k.annotate('text-am') |
|
1019 |
self.assertEquals(origins[0], ('text-a2', 'd\n')) |
|
1020 |
self.assertEquals(origins[1], ('text-a1', 'b\n')) |
|
1021 |
||
1022 |
def test_annotate_merge_2(self): |
|
1563.2.16
by Robert Collins
Change WeaveStore into VersionedFileStore and make its versoined file class parameterisable. |
1023 |
k = self.make_test_knit(True) |
1563.2.4
by Robert Collins
First cut at including the knit implementation of versioned_file. |
1024 |
k.add_lines('text-a1', [], ['a\n', 'b\n', 'c\n']) |
1025 |
k.add_lines('text-a2', [], ['x\n', 'y\n', 'z\n']) |
|
1026 |
k.add_lines('text-am', ['text-a1', 'text-a2'], ['a\n', 'y\n', 'c\n']) |
|
1027 |
origins = k.annotate('text-am') |
|
1028 |
self.assertEquals(origins[0], ('text-a1', 'a\n')) |
|
1029 |
self.assertEquals(origins[1], ('text-a2', 'y\n')) |
|
1030 |
self.assertEquals(origins[2], ('text-a1', 'c\n')) |
|
1031 |
||
1032 |
def test_annotate_merge_9(self): |
|
1563.2.16
by Robert Collins
Change WeaveStore into VersionedFileStore and make its versoined file class parameterisable. |
1033 |
k = self.make_test_knit(True) |
1563.2.4
by Robert Collins
First cut at including the knit implementation of versioned_file. |
1034 |
k.add_lines('text-a1', [], ['a\n', 'b\n', 'c\n']) |
1035 |
k.add_lines('text-a2', [], ['x\n', 'y\n', 'z\n']) |
|
1036 |
k.add_lines('text-am', ['text-a1', 'text-a2'], ['k\n', 'y\n', 'c\n']) |
|
1037 |
origins = k.annotate('text-am') |
|
1038 |
self.assertEquals(origins[0], ('text-am', 'k\n')) |
|
1039 |
self.assertEquals(origins[1], ('text-a2', 'y\n')) |
|
1040 |
self.assertEquals(origins[2], ('text-a1', 'c\n')) |
|
1041 |
||
1042 |
def test_annotate_merge_3(self): |
|
1563.2.16
by Robert Collins
Change WeaveStore into VersionedFileStore and make its versoined file class parameterisable. |
1043 |
k = self.make_test_knit(True) |
1563.2.4
by Robert Collins
First cut at including the knit implementation of versioned_file. |
1044 |
k.add_lines('text-a1', [], ['a\n', 'b\n', 'c\n']) |
1045 |
k.add_lines('text-a2', [] ,['x\n', 'y\n', 'z\n']) |
|
1046 |
k.add_lines('text-am', ['text-a1', 'text-a2'], ['k\n', 'y\n', 'z\n']) |
|
1047 |
origins = k.annotate('text-am') |
|
1048 |
self.assertEquals(origins[0], ('text-am', 'k\n')) |
|
1049 |
self.assertEquals(origins[1], ('text-a2', 'y\n')) |
|
1050 |
self.assertEquals(origins[2], ('text-a2', 'z\n')) |
|
1051 |
||
1052 |
def test_annotate_merge_4(self): |
|
1563.2.16
by Robert Collins
Change WeaveStore into VersionedFileStore and make its versoined file class parameterisable. |
1053 |
k = self.make_test_knit(True) |
1563.2.4
by Robert Collins
First cut at including the knit implementation of versioned_file. |
1054 |
k.add_lines('text-a1', [], ['a\n', 'b\n', 'c\n']) |
1055 |
k.add_lines('text-a2', [], ['x\n', 'y\n', 'z\n']) |
|
1056 |
k.add_lines('text-a3', ['text-a1'], ['a\n', 'b\n', 'p\n']) |
|
1057 |
k.add_lines('text-am', ['text-a2', 'text-a3'], ['a\n', 'b\n', 'z\n']) |
|
1058 |
origins = k.annotate('text-am') |
|
1059 |
self.assertEquals(origins[0], ('text-a1', 'a\n')) |
|
1060 |
self.assertEquals(origins[1], ('text-a1', 'b\n')) |
|
1061 |
self.assertEquals(origins[2], ('text-a2', 'z\n')) |
|
1062 |
||
1063 |
def test_annotate_merge_5(self): |
|
1563.2.16
by Robert Collins
Change WeaveStore into VersionedFileStore and make its versoined file class parameterisable. |
1064 |
k = self.make_test_knit(True) |
1563.2.4
by Robert Collins
First cut at including the knit implementation of versioned_file. |
1065 |
k.add_lines('text-a1', [], ['a\n', 'b\n', 'c\n']) |
1066 |
k.add_lines('text-a2', [], ['d\n', 'e\n', 'f\n']) |
|
1067 |
k.add_lines('text-a3', [], ['x\n', 'y\n', 'z\n']) |
|
1068 |
k.add_lines('text-am', |
|
1069 |
['text-a1', 'text-a2', 'text-a3'], |
|
1070 |
['a\n', 'e\n', 'z\n']) |
|
1071 |
origins = k.annotate('text-am') |
|
1072 |
self.assertEquals(origins[0], ('text-a1', 'a\n')) |
|
1073 |
self.assertEquals(origins[1], ('text-a2', 'e\n')) |
|
1074 |
self.assertEquals(origins[2], ('text-a3', 'z\n')) |
|
1075 |
||
1076 |
def test_annotate_file_cherry_pick(self): |
|
1563.2.16
by Robert Collins
Change WeaveStore into VersionedFileStore and make its versoined file class parameterisable. |
1077 |
k = self.make_test_knit(True) |
1563.2.4
by Robert Collins
First cut at including the knit implementation of versioned_file. |
1078 |
k.add_lines('text-1', [], ['a\n', 'b\n', 'c\n']) |
1079 |
k.add_lines('text-2', ['text-1'], ['d\n', 'e\n', 'f\n']) |
|
1080 |
k.add_lines('text-3', ['text-2', 'text-1'], ['a\n', 'b\n', 'c\n']) |
|
1081 |
origins = k.annotate('text-3') |
|
1082 |
self.assertEquals(origins[0], ('text-1', 'a\n')) |
|
1083 |
self.assertEquals(origins[1], ('text-1', 'b\n')) |
|
1084 |
self.assertEquals(origins[2], ('text-1', 'c\n')) |
|
1085 |
||
1086 |
def test_knit_join(self): |
|
1087 |
"""Store in knit with parents"""
|
|
1685.1.39
by John Arbash Meinel
Updating test_knit to not instantiate a LocalTransport directly. |
1088 |
k1 = KnitVersionedFile('test1', get_transport('.'), factory=KnitPlainFactory(), create=True) |
1563.2.4
by Robert Collins
First cut at including the knit implementation of versioned_file. |
1089 |
k1.add_lines('text-a', [], split_lines(TEXT_1)) |
1090 |
k1.add_lines('text-b', ['text-a'], split_lines(TEXT_1)) |
|
1091 |
||
1092 |
k1.add_lines('text-c', [], split_lines(TEXT_1)) |
|
1093 |
k1.add_lines('text-d', ['text-c'], split_lines(TEXT_1)) |
|
1094 |
||
1095 |
k1.add_lines('text-m', ['text-b', 'text-d'], split_lines(TEXT_1)) |
|
1096 |
||
1685.1.39
by John Arbash Meinel
Updating test_knit to not instantiate a LocalTransport directly. |
1097 |
k2 = KnitVersionedFile('test2', get_transport('.'), factory=KnitPlainFactory(), create=True) |
1563.2.4
by Robert Collins
First cut at including the knit implementation of versioned_file. |
1098 |
count = k2.join(k1, version_ids=['text-m']) |
1099 |
self.assertEquals(count, 5) |
|
1100 |
self.assertTrue(k2.has_version('text-a')) |
|
1101 |
self.assertTrue(k2.has_version('text-c')) |
|
1102 |
||
1103 |
def test_reannotate(self): |
|
1685.1.39
by John Arbash Meinel
Updating test_knit to not instantiate a LocalTransport directly. |
1104 |
k1 = KnitVersionedFile('knit1', get_transport('.'), |
1563.2.25
by Robert Collins
Merge in upstream. |
1105 |
factory=KnitAnnotateFactory(), create=True) |
1563.2.4
by Robert Collins
First cut at including the knit implementation of versioned_file. |
1106 |
# 0
|
1107 |
k1.add_lines('text-a', [], ['a\n', 'b\n']) |
|
1108 |
# 1
|
|
1109 |
k1.add_lines('text-b', ['text-a'], ['a\n', 'c\n']) |
|
1110 |
||
1685.1.39
by John Arbash Meinel
Updating test_knit to not instantiate a LocalTransport directly. |
1111 |
k2 = KnitVersionedFile('test2', get_transport('.'), |
1563.2.25
by Robert Collins
Merge in upstream. |
1112 |
factory=KnitAnnotateFactory(), create=True) |
1563.2.4
by Robert Collins
First cut at including the knit implementation of versioned_file. |
1113 |
k2.join(k1, version_ids=['text-b']) |
1114 |
||
1115 |
# 2
|
|
1116 |
k1.add_lines('text-X', ['text-b'], ['a\n', 'b\n']) |
|
1117 |
# 2
|
|
1118 |
k2.add_lines('text-c', ['text-b'], ['z\n', 'c\n']) |
|
1119 |
# 3
|
|
1120 |
k2.add_lines('text-Y', ['text-b'], ['b\n', 'c\n']) |
|
1121 |
||
1122 |
# test-c will have index 3
|
|
1123 |
k1.join(k2, version_ids=['text-c']) |
|
1124 |
||
1125 |
lines = k1.get_lines('text-c') |
|
1126 |
self.assertEquals(lines, ['z\n', 'c\n']) |
|
1127 |
||
1128 |
origins = k1.annotate('text-c') |
|
1594.2.24
by Robert Collins
Make use of the transaction finalisation warning support to implement in-knit caching. |
1129 |
self.assertEquals(origins[0], ('text-c', 'z\n')) |
1130 |
self.assertEquals(origins[1], ('text-b', 'c\n')) |
|
1131 |
||
1756.3.4
by Aaron Bentley
Fix bug getting texts when line deltas were reused |
1132 |
def test_get_line_delta_texts(self): |
1133 |
"""Make sure we can call get_texts on text with reused line deltas"""
|
|
1134 |
k1 = KnitVersionedFile('test1', get_transport('.'), |
|
1135 |
factory=KnitPlainFactory(), create=True) |
|
1136 |
for t in range(3): |
|
1137 |
if t == 0: |
|
1138 |
parents = [] |
|
1139 |
else: |
|
1140 |
parents = ['%d' % (t-1)] |
|
1141 |
k1.add_lines('%d' % t, parents, ['hello\n'] * t) |
|
1142 |
k1.get_texts(('%d' % t) for t in range(3)) |
|
1594.3.1
by Robert Collins
Merge transaction finalisation and ensure iter_lines_added_or_present in knits does a old-to-new read in the knit. |
1143 |
|
1144 |
def test_iter_lines_reads_in_order(self): |
|
1145 |
t = MemoryTransport() |
|
1146 |
instrumented_t = TransportLogger(t) |
|
1147 |
k1 = KnitVersionedFile('id', instrumented_t, create=True, delta=True) |
|
1148 |
self.assertEqual([('id.kndx',)], instrumented_t._calls) |
|
1149 |
# add texts with no required ordering
|
|
1150 |
k1.add_lines('base', [], ['text\n']) |
|
1151 |
k1.add_lines('base2', [], ['text2\n']) |
|
1152 |
k1.clear_cache() |
|
1153 |
instrumented_t._calls = [] |
|
1154 |
# request a last-first iteration
|
|
1155 |
results = list(k1.iter_lines_added_or_present_in_versions(['base2', 'base'])) |
|
1628.1.2
by Robert Collins
More knit micro-optimisations. |
1156 |
self.assertEqual([('id.knit', [(0, 87), (87, 89)])], instrumented_t._calls) |
1594.3.1
by Robert Collins
Merge transaction finalisation and ensure iter_lines_added_or_present in knits does a old-to-new read in the knit. |
1157 |
self.assertEqual(['text\n', 'text2\n'], results) |
1563.2.4
by Robert Collins
First cut at including the knit implementation of versioned_file. |
1158 |
|
1563.2.13
by Robert Collins
InterVersionedFile implemented. |
1159 |
def test_create_empty_annotated(self): |
1563.2.16
by Robert Collins
Change WeaveStore into VersionedFileStore and make its versoined file class parameterisable. |
1160 |
k1 = self.make_test_knit(True) |
1563.2.13
by Robert Collins
InterVersionedFile implemented. |
1161 |
# 0
|
1162 |
k1.add_lines('text-a', [], ['a\n', 'b\n']) |
|
1163 |
k2 = k1.create_empty('t', MemoryTransport()) |
|
1164 |
self.assertTrue(isinstance(k2.factory, KnitAnnotateFactory)) |
|
1165 |
self.assertEqual(k1.delta, k2.delta) |
|
1166 |
# the generic test checks for empty content and file class
|
|
1167 |
||
1641.1.2
by Robert Collins
Change knit index files to be robust in the presence of partial writes. |
1168 |
def test_knit_format(self): |
1169 |
# this tests that a new knit index file has the expected content
|
|
1170 |
# and that is writes the data we expect as records are added.
|
|
1171 |
knit = self.make_test_knit(True) |
|
1946.2.1
by John Arbash Meinel
2 changes to knits. Delay creating the .knit or .kndx file until we have actually tried to write data. Because of this, we must allow the Knit to create the prefix directories |
1172 |
# Now knit files are not created until we first add data to them
|
1666.1.6
by Robert Collins
Make knit the default format. |
1173 |
self.assertFileEqual("# bzr knit index 8\n", 'test.kndx') |
1641.1.2
by Robert Collins
Change knit index files to be robust in the presence of partial writes. |
1174 |
knit.add_lines_with_ghosts('revid', ['a_ghost'], ['a\n']) |
1175 |
self.assertFileEqual( |
|
1666.1.6
by Robert Collins
Make knit the default format. |
1176 |
"# bzr knit index 8\n" |
1641.1.2
by Robert Collins
Change knit index files to be robust in the presence of partial writes. |
1177 |
"\n" |
1178 |
"revid fulltext 0 84 .a_ghost :", |
|
1179 |
'test.kndx') |
|
1180 |
knit.add_lines_with_ghosts('revid2', ['revid'], ['a\n']) |
|
1181 |
self.assertFileEqual( |
|
1666.1.6
by Robert Collins
Make knit the default format. |
1182 |
"# bzr knit index 8\n" |
1641.1.2
by Robert Collins
Change knit index files to be robust in the presence of partial writes. |
1183 |
"\nrevid fulltext 0 84 .a_ghost :" |
1184 |
"\nrevid2 line-delta 84 82 0 :", |
|
1185 |
'test.kndx') |
|
1186 |
# we should be able to load this file again
|
|
1685.1.39
by John Arbash Meinel
Updating test_knit to not instantiate a LocalTransport directly. |
1187 |
knit = KnitVersionedFile('test', get_transport('.'), access_mode='r') |
1641.1.2
by Robert Collins
Change knit index files to be robust in the presence of partial writes. |
1188 |
self.assertEqual(['revid', 'revid2'], knit.versions()) |
1189 |
# write a short write to the file and ensure that its ignored
|
|
2484.1.23
by John Arbash Meinel
When we append a new line, don't use text mode |
1190 |
indexfile = file('test.kndx', 'ab') |
1641.1.2
by Robert Collins
Change knit index files to be robust in the presence of partial writes. |
1191 |
indexfile.write('\nrevid3 line-delta 166 82 1 2 3 4 5 .phwoar:demo ') |
1192 |
indexfile.close() |
|
1193 |
# we should be able to load this file again
|
|
1685.1.39
by John Arbash Meinel
Updating test_knit to not instantiate a LocalTransport directly. |
1194 |
knit = KnitVersionedFile('test', get_transport('.'), access_mode='w') |
1654.1.5
by Robert Collins
Merge partial index write support for knits, adding a test case per review comments. |
1195 |
self.assertEqual(['revid', 'revid2'], knit.versions()) |
1196 |
# and add a revision with the same id the failed write had
|
|
1197 |
knit.add_lines('revid3', ['revid2'], ['a\n']) |
|
1198 |
# and when reading it revid3 should now appear.
|
|
1685.1.39
by John Arbash Meinel
Updating test_knit to not instantiate a LocalTransport directly. |
1199 |
knit = KnitVersionedFile('test', get_transport('.'), access_mode='r') |
1654.1.5
by Robert Collins
Merge partial index write support for knits, adding a test case per review comments. |
1200 |
self.assertEqual(['revid', 'revid2', 'revid3'], knit.versions()) |
1201 |
self.assertEqual(['revid2'], knit.get_parents('revid3')) |
|
1202 |
||
1946.2.1
by John Arbash Meinel
2 changes to knits. Delay creating the .knit or .kndx file until we have actually tried to write data. Because of this, we must allow the Knit to create the prefix directories |
1203 |
def test_delay_create(self): |
1204 |
"""Test that passing delay_create=True creates files late"""
|
|
1205 |
knit = self.make_test_knit(annotate=True, delay_create=True) |
|
1206 |
self.failIfExists('test.knit') |
|
1207 |
self.failIfExists('test.kndx') |
|
1208 |
knit.add_lines_with_ghosts('revid', ['a_ghost'], ['a\n']) |
|
1209 |
self.failUnlessExists('test.knit') |
|
1210 |
self.assertFileEqual( |
|
1211 |
"# bzr knit index 8\n" |
|
1212 |
"\n" |
|
1213 |
"revid fulltext 0 84 .a_ghost :", |
|
1214 |
'test.kndx') |
|
1215 |
||
1946.2.2
by John Arbash Meinel
test delay_create does the right thing |
1216 |
def test_create_parent_dir(self): |
1217 |
"""create_parent_dir can create knits in nonexistant dirs"""
|
|
1218 |
# Has no effect if we don't set 'delay_create'
|
|
1219 |
trans = get_transport('.') |
|
1220 |
self.assertRaises(NoSuchFile, KnitVersionedFile, 'dir/test', |
|
1221 |
trans, access_mode='w', factory=None, |
|
1222 |
create=True, create_parent_dir=True) |
|
1223 |
# Nothing should have changed yet
|
|
1224 |
knit = KnitVersionedFile('dir/test', trans, access_mode='w', |
|
1225 |
factory=None, create=True, |
|
1226 |
create_parent_dir=True, |
|
1227 |
delay_create=True) |
|
1228 |
self.failIfExists('dir/test.knit') |
|
1229 |
self.failIfExists('dir/test.kndx') |
|
1230 |
self.failIfExists('dir') |
|
1231 |
knit.add_lines('revid', [], ['a\n']) |
|
1232 |
self.failUnlessExists('dir') |
|
1233 |
self.failUnlessExists('dir/test.knit') |
|
1234 |
self.assertFileEqual( |
|
1235 |
"# bzr knit index 8\n" |
|
1236 |
"\n" |
|
1237 |
"revid fulltext 0 84 :", |
|
1238 |
'dir/test.kndx') |
|
1239 |
||
1946.2.13
by John Arbash Meinel
Test that passing modes does the right thing for knits. |
1240 |
def test_create_mode_700(self): |
1241 |
trans = get_transport('.') |
|
1242 |
if not trans._can_roundtrip_unix_modebits(): |
|
1243 |
# Can't roundtrip, so no need to run this test
|
|
1244 |
return
|
|
1245 |
knit = KnitVersionedFile('dir/test', trans, access_mode='w', |
|
1246 |
factory=None, create=True, |
|
1247 |
create_parent_dir=True, |
|
1248 |
delay_create=True, |
|
1249 |
file_mode=0600, |
|
1250 |
dir_mode=0700) |
|
1251 |
knit.add_lines('revid', [], ['a\n']) |
|
1252 |
self.assertTransportMode(trans, 'dir', 0700) |
|
1253 |
self.assertTransportMode(trans, 'dir/test.knit', 0600) |
|
1254 |
self.assertTransportMode(trans, 'dir/test.kndx', 0600) |
|
1255 |
||
1256 |
def test_create_mode_770(self): |
|
1257 |
trans = get_transport('.') |
|
1258 |
if not trans._can_roundtrip_unix_modebits(): |
|
1259 |
# Can't roundtrip, so no need to run this test
|
|
1260 |
return
|
|
1261 |
knit = KnitVersionedFile('dir/test', trans, access_mode='w', |
|
1262 |
factory=None, create=True, |
|
1263 |
create_parent_dir=True, |
|
1264 |
delay_create=True, |
|
1265 |
file_mode=0660, |
|
1266 |
dir_mode=0770) |
|
1267 |
knit.add_lines('revid', [], ['a\n']) |
|
1268 |
self.assertTransportMode(trans, 'dir', 0770) |
|
1269 |
self.assertTransportMode(trans, 'dir/test.knit', 0660) |
|
1270 |
self.assertTransportMode(trans, 'dir/test.kndx', 0660) |
|
1271 |
||
1272 |
def test_create_mode_777(self): |
|
1273 |
trans = get_transport('.') |
|
1274 |
if not trans._can_roundtrip_unix_modebits(): |
|
1275 |
# Can't roundtrip, so no need to run this test
|
|
1276 |
return
|
|
1277 |
knit = KnitVersionedFile('dir/test', trans, access_mode='w', |
|
1278 |
factory=None, create=True, |
|
1279 |
create_parent_dir=True, |
|
1280 |
delay_create=True, |
|
1281 |
file_mode=0666, |
|
1282 |
dir_mode=0777) |
|
1283 |
knit.add_lines('revid', [], ['a\n']) |
|
1284 |
self.assertTransportMode(trans, 'dir', 0777) |
|
1285 |
self.assertTransportMode(trans, 'dir/test.knit', 0666) |
|
1286 |
self.assertTransportMode(trans, 'dir/test.kndx', 0666) |
|
1287 |
||
1664.2.1
by Aaron Bentley
Start work on plan_merge test |
1288 |
def test_plan_merge(self): |
1289 |
my_knit = self.make_test_knit(annotate=True) |
|
1290 |
my_knit.add_lines('text1', [], split_lines(TEXT_1)) |
|
1291 |
my_knit.add_lines('text1a', ['text1'], split_lines(TEXT_1A)) |
|
1292 |
my_knit.add_lines('text1b', ['text1'], split_lines(TEXT_1B)) |
|
1664.2.3
by Aaron Bentley
Add failing test case |
1293 |
plan = list(my_knit.plan_merge('text1a', 'text1b')) |
1664.2.6
by Aaron Bentley
Got plan-merge passing tests |
1294 |
for plan_line, expected_line in zip(plan, AB_MERGE): |
1295 |
self.assertEqual(plan_line, expected_line) |
|
1641.1.2
by Robert Collins
Change knit index files to be robust in the presence of partial writes. |
1296 |
|
1563.2.4
by Robert Collins
First cut at including the knit implementation of versioned_file. |
1297 |
|
1298 |
TEXT_1 = """\ |
|
1299 |
Banana cup cakes:
|
|
1300 |
||
1301 |
- bananas
|
|
1302 |
- eggs
|
|
1303 |
- broken tea cups
|
|
1304 |
"""
|
|
1305 |
||
1306 |
TEXT_1A = """\ |
|
1307 |
Banana cup cake recipe
|
|
1308 |
(serves 6)
|
|
1309 |
||
1310 |
- bananas
|
|
1311 |
- eggs
|
|
1312 |
- broken tea cups
|
|
1313 |
- self-raising flour
|
|
1314 |
"""
|
|
1315 |
||
1664.2.1
by Aaron Bentley
Start work on plan_merge test |
1316 |
TEXT_1B = """\ |
1317 |
Banana cup cake recipe
|
|
1318 |
||
1319 |
- bananas (do not use plantains!!!)
|
|
1320 |
- broken tea cups
|
|
1321 |
- flour
|
|
1322 |
"""
|
|
1323 |
||
1563.2.4
by Robert Collins
First cut at including the knit implementation of versioned_file. |
1324 |
delta_1_1a = """\ |
1325 |
0,1,2
|
|
1326 |
Banana cup cake recipe
|
|
1327 |
(serves 6)
|
|
1328 |
5,5,1
|
|
1329 |
- self-raising flour
|
|
1330 |
"""
|
|
1331 |
||
1332 |
TEXT_2 = """\ |
|
1333 |
Boeuf bourguignon
|
|
1334 |
||
1335 |
- beef
|
|
1336 |
- red wine
|
|
1337 |
- small onions
|
|
1338 |
- carrot
|
|
1339 |
- mushrooms
|
|
1340 |
"""
|
|
1341 |
||
1664.2.3
by Aaron Bentley
Add failing test case |
1342 |
AB_MERGE_TEXT="""unchanged|Banana cup cake recipe |
1343 |
new-a|(serves 6)
|
|
1344 |
unchanged|
|
|
1345 |
killed-b|- bananas
|
|
1346 |
killed-b|- eggs
|
|
1347 |
new-b|- bananas (do not use plantains!!!)
|
|
1348 |
unchanged|- broken tea cups
|
|
1349 |
new-a|- self-raising flour
|
|
1664.2.6
by Aaron Bentley
Got plan-merge passing tests |
1350 |
new-b|- flour
|
1351 |
"""
|
|
1664.2.3
by Aaron Bentley
Add failing test case |
1352 |
AB_MERGE=[tuple(l.split('|')) for l in AB_MERGE_TEXT.splitlines(True)] |
1353 |
||
1354 |
||
1563.2.4
by Robert Collins
First cut at including the knit implementation of versioned_file. |
1355 |
def line_delta(from_lines, to_lines): |
1356 |
"""Generate line-based delta from one text to another"""
|
|
1357 |
s = difflib.SequenceMatcher(None, from_lines, to_lines) |
|
1358 |
for op in s.get_opcodes(): |
|
1359 |
if op[0] == 'equal': |
|
1360 |
continue
|
|
1361 |
yield '%d,%d,%d\n' % (op[1], op[2], op[4]-op[3]) |
|
1362 |
for i in range(op[3], op[4]): |
|
1363 |
yield to_lines[i] |
|
1364 |
||
1365 |
||
1366 |
def apply_line_delta(basis_lines, delta_lines): |
|
1367 |
"""Apply a line-based perfect diff
|
|
1368 |
|
|
1369 |
basis_lines -- text to apply the patch to
|
|
1370 |
delta_lines -- diff instructions and content
|
|
1371 |
"""
|
|
1372 |
out = basis_lines[:] |
|
1373 |
i = 0 |
|
1374 |
offset = 0 |
|
1375 |
while i < len(delta_lines): |
|
1376 |
l = delta_lines[i] |
|
1377 |
a, b, c = map(long, l.split(',')) |
|
1378 |
i = i + 1 |
|
1379 |
out[offset+a:offset+b] = delta_lines[i:i+c] |
|
1380 |
i = i + c |
|
1381 |
offset = offset + (b - a) + c |
|
1382 |
return out |
|
1684.3.3
by Robert Collins
Add a special cased weaves to knit converter. |
1383 |
|
1384 |
||
1385 |
class TestWeaveToKnit(KnitTests): |
|
1386 |
||
1387 |
def test_weave_to_knit_matches(self): |
|
1388 |
# check that the WeaveToKnit is_compatible function
|
|
1389 |
# registers True for a Weave to a Knit.
|
|
1390 |
w = Weave() |
|
1391 |
k = self.make_test_knit() |
|
1392 |
self.failUnless(WeaveToKnit.is_compatible(w, k)) |
|
1393 |
self.failIf(WeaveToKnit.is_compatible(k, w)) |
|
1394 |
self.failIf(WeaveToKnit.is_compatible(w, w)) |
|
1395 |
self.failIf(WeaveToKnit.is_compatible(k, k)) |
|
1863.1.1
by John Arbash Meinel
Allow Versioned files to do caching if explicitly asked, and implement for Knit |
1396 |
|
1397 |
||
1398 |
class TestKnitCaching(KnitTests): |
|
1399 |
||
1400 |
def create_knit(self, cache_add=False): |
|
1401 |
k = self.make_test_knit(True) |
|
1402 |
if cache_add: |
|
1403 |
k.enable_cache() |
|
1404 |
||
1405 |
k.add_lines('text-1', [], split_lines(TEXT_1)) |
|
1406 |
k.add_lines('text-2', [], split_lines(TEXT_2)) |
|
1407 |
return k |
|
1408 |
||
1409 |
def test_no_caching(self): |
|
1410 |
k = self.create_knit() |
|
1411 |
# Nothing should be cached without setting 'enable_cache'
|
|
1412 |
self.assertEqual({}, k._data._cache) |
|
1413 |
||
1414 |
def test_cache_add_and_clear(self): |
|
1415 |
k = self.create_knit(True) |
|
1416 |
||
1417 |
self.assertEqual(['text-1', 'text-2'], sorted(k._data._cache.keys())) |
|
1418 |
||
1419 |
k.clear_cache() |
|
1420 |
self.assertEqual({}, k._data._cache) |
|
1421 |
||
1422 |
def test_cache_data_read_raw(self): |
|
1423 |
k = self.create_knit() |
|
1424 |
||
1425 |
# Now cache and read
|
|
1426 |
k.enable_cache() |
|
1427 |
||
1428 |
def read_one_raw(version): |
|
1429 |
pos_map = k._get_components_positions([version]) |
|
1430 |
method, pos, size, next = pos_map[version] |
|
1431 |
lst = list(k._data.read_records_iter_raw([(version, pos, size)])) |
|
1432 |
self.assertEqual(1, len(lst)) |
|
1433 |
return lst[0] |
|
1434 |
||
1435 |
val = read_one_raw('text-1') |
|
1863.1.8
by John Arbash Meinel
Removing disk-backed-cache |
1436 |
self.assertEqual({'text-1':val[1]}, k._data._cache) |
1863.1.1
by John Arbash Meinel
Allow Versioned files to do caching if explicitly asked, and implement for Knit |
1437 |
|
1438 |
k.clear_cache() |
|
1439 |
# After clear, new reads are not cached
|
|
1440 |
self.assertEqual({}, k._data._cache) |
|
1441 |
||
1442 |
val2 = read_one_raw('text-1') |
|
1443 |
self.assertEqual(val, val2) |
|
1444 |
self.assertEqual({}, k._data._cache) |
|
1445 |
||
1446 |
def test_cache_data_read(self): |
|
1447 |
k = self.create_knit() |
|
1448 |
||
1449 |
def read_one(version): |
|
1450 |
pos_map = k._get_components_positions([version]) |
|
1451 |
method, pos, size, next = pos_map[version] |
|
1452 |
lst = list(k._data.read_records_iter([(version, pos, size)])) |
|
1453 |
self.assertEqual(1, len(lst)) |
|
1454 |
return lst[0] |
|
1455 |
||
1456 |
# Now cache and read
|
|
1457 |
k.enable_cache() |
|
1458 |
||
1459 |
val = read_one('text-2') |
|
1460 |
self.assertEqual(['text-2'], k._data._cache.keys()) |
|
1461 |
self.assertEqual('text-2', val[0]) |
|
1462 |
content, digest = k._data._parse_record('text-2', |
|
1463 |
k._data._cache['text-2']) |
|
1464 |
self.assertEqual(content, val[1]) |
|
1465 |
self.assertEqual(digest, val[2]) |
|
1466 |
||
1467 |
k.clear_cache() |
|
1468 |
self.assertEqual({}, k._data._cache) |
|
1469 |
||
1470 |
val2 = read_one('text-2') |
|
1471 |
self.assertEqual(val, val2) |
|
1472 |
self.assertEqual({}, k._data._cache) |
|
1473 |
||
1474 |
def test_cache_read(self): |
|
1475 |
k = self.create_knit() |
|
1476 |
k.enable_cache() |
|
1477 |
||
1478 |
text = k.get_text('text-1') |
|
1479 |
self.assertEqual(TEXT_1, text) |
|
1480 |
self.assertEqual(['text-1'], k._data._cache.keys()) |
|
1481 |
||
1482 |
k.clear_cache() |
|
1483 |
self.assertEqual({}, k._data._cache) |
|
1484 |
||
1485 |
text = k.get_text('text-1') |
|
1486 |
self.assertEqual(TEXT_1, text) |
|
1487 |
self.assertEqual({}, k._data._cache) |
|
2102.2.1
by John Arbash Meinel
Fix bug #64789 _KnitIndex.add_versions() should dict compress new revisions |
1488 |
|
1489 |
||
1490 |
class TestKnitIndex(KnitTests): |
|
1491 |
||
1492 |
def test_add_versions_dictionary_compresses(self): |
|
1493 |
"""Adding versions to the index should update the lookup dict"""
|
|
1494 |
knit = self.make_test_knit() |
|
1495 |
idx = knit._index |
|
1496 |
idx.add_version('a-1', ['fulltext'], 0, 0, []) |
|
1497 |
self.check_file_contents('test.kndx', |
|
1498 |
'# bzr knit index 8\n' |
|
1499 |
'\n' |
|
1500 |
'a-1 fulltext 0 0 :'
|
|
1501 |
)
|
|
1502 |
idx.add_versions([('a-2', ['fulltext'], 0, 0, ['a-1']), |
|
1503 |
('a-3', ['fulltext'], 0, 0, ['a-2']), |
|
1504 |
])
|
|
1505 |
self.check_file_contents('test.kndx', |
|
1506 |
'# bzr knit index 8\n' |
|
1507 |
'\n' |
|
1508 |
'a-1 fulltext 0 0 :\n' |
|
1509 |
'a-2 fulltext 0 0 0 :\n' |
|
1510 |
'a-3 fulltext 0 0 1 :'
|
|
1511 |
)
|
|
1512 |
self.assertEqual(['a-1', 'a-2', 'a-3'], idx._history) |
|
1513 |
self.assertEqual({'a-1':('a-1', ['fulltext'], 0, 0, [], 0), |
|
1514 |
'a-2':('a-2', ['fulltext'], 0, 0, ['a-1'], 1), |
|
1515 |
'a-3':('a-3', ['fulltext'], 0, 0, ['a-2'], 2), |
|
1516 |
}, idx._cache) |
|
1517 |
||
1518 |
def test_add_versions_fails_clean(self): |
|
1519 |
"""If add_versions fails in the middle, it restores a pristine state.
|
|
1520 |
||
1521 |
Any modifications that are made to the index are reset if all versions
|
|
1522 |
cannot be added.
|
|
1523 |
"""
|
|
1524 |
# This cheats a little bit by passing in a generator which will
|
|
1525 |
# raise an exception before the processing finishes
|
|
1526 |
# Other possibilities would be to have an version with the wrong number
|
|
1527 |
# of entries, or to make the backing transport unable to write any
|
|
1528 |
# files.
|
|
1529 |
||
1530 |
knit = self.make_test_knit() |
|
1531 |
idx = knit._index |
|
1532 |
idx.add_version('a-1', ['fulltext'], 0, 0, []) |
|
1533 |
||
1534 |
class StopEarly(Exception): |
|
1535 |
pass
|
|
1536 |
||
1537 |
def generate_failure(): |
|
1538 |
"""Add some entries and then raise an exception"""
|
|
1539 |
yield ('a-2', ['fulltext'], 0, 0, ['a-1']) |
|
1540 |
yield ('a-3', ['fulltext'], 0, 0, ['a-2']) |
|
1541 |
raise StopEarly() |
|
1542 |
||
1543 |
# Assert the pre-condition
|
|
1544 |
self.assertEqual(['a-1'], idx._history) |
|
1545 |
self.assertEqual({'a-1':('a-1', ['fulltext'], 0, 0, [], 0)}, idx._cache) |
|
1546 |
||
1547 |
self.assertRaises(StopEarly, idx.add_versions, generate_failure()) |
|
1548 |
||
1549 |
# And it shouldn't be modified
|
|
1550 |
self.assertEqual(['a-1'], idx._history) |
|
1551 |
self.assertEqual({'a-1':('a-1', ['fulltext'], 0, 0, [], 0)}, idx._cache) |
|
2171.1.1
by John Arbash Meinel
Knit index files should ignore empty indexes rather than consider them corrupt. |
1552 |
|
1553 |
def test_knit_index_ignores_empty_files(self): |
|
1554 |
# There was a race condition in older bzr, where a ^C at the right time
|
|
1555 |
# could leave an empty .kndx file, which bzr would later claim was a
|
|
1556 |
# corrupted file since the header was not present. In reality, the file
|
|
1557 |
# just wasn't created, so it should be ignored.
|
|
1558 |
t = get_transport('.') |
|
1559 |
t.put_bytes('test.kndx', '') |
|
1560 |
||
1561 |
knit = self.make_test_knit() |
|
1562 |
||
1563 |
def test_knit_index_checks_header(self): |
|
1564 |
t = get_transport('.') |
|
1565 |
t.put_bytes('test.kndx', '# not really a knit header\n\n') |
|
1566 |
||
2196.2.1
by John Arbash Meinel
Merge Dmitry's optimizations and minimize the actual diff. |
1567 |
self.assertRaises(KnitHeaderError, self.make_test_knit) |