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, |
2670.2.2
by Robert Collins
* In ``bzrlib.knit`` the internal interface has been altered to use |
29 |
pack, |
2196.2.5
by John Arbash Meinel
Add an exception class when the knit index storage method is unknown, and properly test for it |
30 |
)
|
2158.3.1
by Dmitry Vasiliev
KnitIndex tests/fixes/optimizations |
31 |
from bzrlib.errors import ( |
32 |
RevisionAlreadyPresent, |
|
33 |
KnitHeaderError, |
|
34 |
RevisionNotPresent, |
|
35 |
NoSuchFile, |
|
36 |
)
|
|
2625.8.1
by Robert Collins
LIBRARY API BREAKS: |
37 |
from bzrlib.index import * |
1684.3.3
by Robert Collins
Add a special cased weaves to knit converter. |
38 |
from bzrlib.knit import ( |
2151.1.1
by John Arbash Meinel
(Dmitry Vasiliev) Tune KnitContent and add tests |
39 |
KnitContent, |
2625.8.1
by Robert Collins
LIBRARY API BREAKS: |
40 |
KnitGraphIndex, |
1684.3.3
by Robert Collins
Add a special cased weaves to knit converter. |
41 |
KnitVersionedFile, |
42 |
KnitPlainFactory, |
|
43 |
KnitAnnotateFactory, |
|
2670.2.2
by Robert Collins
* In ``bzrlib.knit`` the internal interface has been altered to use |
44 |
_KnitAccess, |
2329.1.1
by John Arbash Meinel
Update _KnitData parser to raise more helpful errors when it detects corruption. |
45 |
_KnitData, |
2158.3.1
by Dmitry Vasiliev
KnitIndex tests/fixes/optimizations |
46 |
_KnitIndex, |
2670.2.2
by Robert Collins
* In ``bzrlib.knit`` the internal interface has been altered to use |
47 |
_PackAccess, |
2158.3.1
by Dmitry Vasiliev
KnitIndex tests/fixes/optimizations |
48 |
WeaveToKnit, |
2520.4.41
by Aaron Bentley
Accelerate mpdiff generation |
49 |
KnitSequenceMatcher, |
2158.3.1
by Dmitry Vasiliev
KnitIndex tests/fixes/optimizations |
50 |
)
|
1563.2.4
by Robert Collins
First cut at including the knit implementation of versioned_file. |
51 |
from bzrlib.osutils import split_lines |
2670.2.2
by Robert Collins
* In ``bzrlib.knit`` the internal interface has been altered to use |
52 |
from bzrlib.tests import ( |
53 |
Feature, |
|
54 |
TestCase, |
|
55 |
TestCaseWithMemoryTransport, |
|
56 |
TestCaseWithTransport, |
|
57 |
)
|
|
1685.1.39
by John Arbash Meinel
Updating test_knit to not instantiate a LocalTransport directly. |
58 |
from bzrlib.transport import TransportLogger, get_transport |
1563.2.13
by Robert Collins
InterVersionedFile implemented. |
59 |
from bzrlib.transport.memory import MemoryTransport |
2670.3.1
by Andrew Bennetts
Add get_data_stream/insert_data_stream to KnitVersionedFile. |
60 |
from bzrlib.util import bencode |
1684.3.3
by Robert Collins
Add a special cased weaves to knit converter. |
61 |
from bzrlib.weave import Weave |
62 |
||
63 |
||
2484.1.1
by John Arbash Meinel
Add an initial function to read knit indexes in pyrex. |
64 |
class _CompiledKnitFeature(Feature): |
65 |
||
66 |
def _probe(self): |
|
67 |
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 |
68 |
import bzrlib._knit_load_data_c |
2484.1.1
by John Arbash Meinel
Add an initial function to read knit indexes in pyrex. |
69 |
except ImportError: |
70 |
return False |
|
71 |
return True |
|
72 |
||
73 |
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 |
74 |
return 'bzrlib._knit_load_data_c' |
2484.1.1
by John Arbash Meinel
Add an initial function to read knit indexes in pyrex. |
75 |
|
76 |
CompiledKnitFeature = _CompiledKnitFeature() |
|
77 |
||
78 |
||
2151.1.1
by John Arbash Meinel
(Dmitry Vasiliev) Tune KnitContent and add tests |
79 |
class KnitContentTests(TestCase): |
80 |
||
81 |
def test_constructor(self): |
|
82 |
content = KnitContent([]) |
|
83 |
||
84 |
def test_text(self): |
|
85 |
content = KnitContent([]) |
|
86 |
self.assertEqual(content.text(), []) |
|
87 |
||
88 |
content = KnitContent([("origin1", "text1"), ("origin2", "text2")]) |
|
89 |
self.assertEqual(content.text(), ["text1", "text2"]) |
|
90 |
||
91 |
def test_annotate(self): |
|
92 |
content = KnitContent([]) |
|
93 |
self.assertEqual(content.annotate(), []) |
|
94 |
||
95 |
content = KnitContent([("origin1", "text1"), ("origin2", "text2")]) |
|
96 |
self.assertEqual(content.annotate(), |
|
97 |
[("origin1", "text1"), ("origin2", "text2")]) |
|
98 |
||
99 |
def test_annotate_iter(self): |
|
100 |
content = KnitContent([]) |
|
101 |
it = content.annotate_iter() |
|
102 |
self.assertRaises(StopIteration, it.next) |
|
103 |
||
104 |
content = KnitContent([("origin1", "text1"), ("origin2", "text2")]) |
|
105 |
it = content.annotate_iter() |
|
106 |
self.assertEqual(it.next(), ("origin1", "text1")) |
|
107 |
self.assertEqual(it.next(), ("origin2", "text2")) |
|
108 |
self.assertRaises(StopIteration, it.next) |
|
109 |
||
110 |
def test_copy(self): |
|
111 |
content = KnitContent([("origin1", "text1"), ("origin2", "text2")]) |
|
112 |
copy = content.copy() |
|
113 |
self.assertIsInstance(copy, KnitContent) |
|
114 |
self.assertEqual(copy.annotate(), |
|
115 |
[("origin1", "text1"), ("origin2", "text2")]) |
|
116 |
||
117 |
def test_line_delta(self): |
|
118 |
content1 = KnitContent([("", "a"), ("", "b")]) |
|
119 |
content2 = KnitContent([("", "a"), ("", "a"), ("", "c")]) |
|
120 |
self.assertEqual(content1.line_delta(content2), |
|
121 |
[(1, 2, 2, [("", "a"), ("", "c")])]) |
|
122 |
||
123 |
def test_line_delta_iter(self): |
|
124 |
content1 = KnitContent([("", "a"), ("", "b")]) |
|
125 |
content2 = KnitContent([("", "a"), ("", "a"), ("", "c")]) |
|
126 |
it = content1.line_delta_iter(content2) |
|
127 |
self.assertEqual(it.next(), (1, 2, 2, [("", "a"), ("", "c")])) |
|
128 |
self.assertRaises(StopIteration, it.next) |
|
129 |
||
2158.3.1
by Dmitry Vasiliev
KnitIndex tests/fixes/optimizations |
130 |
|
131 |
class MockTransport(object): |
|
132 |
||
133 |
def __init__(self, file_lines=None): |
|
134 |
self.file_lines = file_lines |
|
135 |
self.calls = [] |
|
2196.2.3
by John Arbash Meinel
Update tests and code to pass after merging bzr.dev |
136 |
# We have no base directory for the MockTransport
|
137 |
self.base = '' |
|
2158.3.1
by Dmitry Vasiliev
KnitIndex tests/fixes/optimizations |
138 |
|
139 |
def get(self, filename): |
|
140 |
if self.file_lines is None: |
|
141 |
raise NoSuchFile(filename) |
|
142 |
else: |
|
143 |
return StringIO("\n".join(self.file_lines)) |
|
144 |
||
2329.1.1
by John Arbash Meinel
Update _KnitData parser to raise more helpful errors when it detects corruption. |
145 |
def readv(self, relpath, offsets): |
146 |
fp = self.get(relpath) |
|
147 |
for offset, size in offsets: |
|
148 |
fp.seek(offset) |
|
149 |
yield offset, fp.read(size) |
|
150 |
||
2158.3.1
by Dmitry Vasiliev
KnitIndex tests/fixes/optimizations |
151 |
def __getattr__(self, name): |
152 |
def queue_call(*args, **kwargs): |
|
153 |
self.calls.append((name, args, kwargs)) |
|
154 |
return queue_call |
|
155 |
||
156 |
||
2670.2.2
by Robert Collins
* In ``bzrlib.knit`` the internal interface has been altered to use |
157 |
class KnitRecordAccessTestsMixin(object): |
158 |
"""Tests for getting and putting knit records."""
|
|
159 |
||
160 |
def assertAccessExists(self, access): |
|
161 |
"""Ensure the data area for access has been initialised/exists."""
|
|
162 |
raise NotImplementedError(self.assertAccessExists) |
|
163 |
||
164 |
def test_add_raw_records(self): |
|
165 |
"""Add_raw_records adds records retrievable later."""
|
|
166 |
access = self.get_access() |
|
167 |
memos = access.add_raw_records([10], '1234567890') |
|
168 |
self.assertEqual(['1234567890'], list(access.get_raw_records(memos))) |
|
169 |
||
170 |
def test_add_several_raw_records(self): |
|
171 |
"""add_raw_records with many records and read some back."""
|
|
172 |
access = self.get_access() |
|
173 |
memos = access.add_raw_records([10, 2, 5], '12345678901234567') |
|
174 |
self.assertEqual(['1234567890', '12', '34567'], |
|
175 |
list(access.get_raw_records(memos))) |
|
176 |
self.assertEqual(['1234567890'], |
|
177 |
list(access.get_raw_records(memos[0:1]))) |
|
178 |
self.assertEqual(['12'], |
|
179 |
list(access.get_raw_records(memos[1:2]))) |
|
180 |
self.assertEqual(['34567'], |
|
181 |
list(access.get_raw_records(memos[2:3]))) |
|
182 |
self.assertEqual(['1234567890', '34567'], |
|
183 |
list(access.get_raw_records(memos[0:1] + memos[2:3]))) |
|
184 |
||
185 |
def test_create(self): |
|
186 |
"""create() should make a file on disk."""
|
|
187 |
access = self.get_access() |
|
188 |
access.create() |
|
189 |
self.assertAccessExists(access) |
|
190 |
||
191 |
def test_open_file(self): |
|
192 |
"""open_file never errors."""
|
|
193 |
access = self.get_access() |
|
194 |
access.open_file() |
|
195 |
||
196 |
||
197 |
class TestKnitKnitAccess(TestCaseWithMemoryTransport, KnitRecordAccessTestsMixin): |
|
198 |
"""Tests for the .kndx implementation."""
|
|
199 |
||
200 |
def assertAccessExists(self, access): |
|
201 |
self.assertNotEqual(None, access.open_file()) |
|
202 |
||
203 |
def get_access(self): |
|
204 |
"""Get a .knit style access instance."""
|
|
205 |
access = _KnitAccess(self.get_transport(), "foo.knit", None, None, |
|
206 |
False, False) |
|
207 |
return access |
|
208 |
||
209 |
||
210 |
class TestPackKnitAccess(TestCaseWithMemoryTransport, KnitRecordAccessTestsMixin): |
|
211 |
"""Tests for the pack based access."""
|
|
212 |
||
213 |
def assertAccessExists(self, access): |
|
214 |
# as pack based access has no backing unless an index maps data, this
|
|
215 |
# is a no-op.
|
|
216 |
pass
|
|
217 |
||
218 |
def get_access(self): |
|
219 |
return self._get_access()[0] |
|
220 |
||
221 |
def _get_access(self, packname='packfile', index='FOO'): |
|
222 |
transport = self.get_transport() |
|
223 |
def write_data(bytes): |
|
224 |
transport.append_bytes(packname, bytes) |
|
225 |
writer = pack.ContainerWriter(write_data) |
|
226 |
writer.begin() |
|
227 |
indices = {index:(transport, packname)} |
|
228 |
access = _PackAccess(indices, writer=(writer, index)) |
|
229 |
return access, writer |
|
230 |
||
231 |
def test_read_from_several_packs(self): |
|
232 |
access, writer = self._get_access() |
|
233 |
memos = [] |
|
234 |
memos.extend(access.add_raw_records([10], '1234567890')) |
|
235 |
writer.end() |
|
236 |
access, writer = self._get_access('pack2', 'FOOBAR') |
|
237 |
memos.extend(access.add_raw_records([5], '12345')) |
|
238 |
writer.end() |
|
239 |
access, writer = self._get_access('pack3', 'BAZ') |
|
240 |
memos.extend(access.add_raw_records([5], 'alpha')) |
|
241 |
writer.end() |
|
242 |
transport = self.get_transport() |
|
243 |
access = _PackAccess({"FOO":(transport, 'packfile'), |
|
244 |
"FOOBAR":(transport, 'pack2'), |
|
245 |
"BAZ":(transport, 'pack3')}) |
|
246 |
self.assertEqual(['1234567890', '12345', 'alpha'], |
|
247 |
list(access.get_raw_records(memos))) |
|
248 |
self.assertEqual(['1234567890'], |
|
249 |
list(access.get_raw_records(memos[0:1]))) |
|
250 |
self.assertEqual(['12345'], |
|
251 |
list(access.get_raw_records(memos[1:2]))) |
|
252 |
self.assertEqual(['alpha'], |
|
253 |
list(access.get_raw_records(memos[2:3]))) |
|
254 |
self.assertEqual(['1234567890', 'alpha'], |
|
255 |
list(access.get_raw_records(memos[0:1] + memos[2:3]))) |
|
256 |
||
257 |
def test_set_writer(self): |
|
258 |
"""The writer should be settable post construction."""
|
|
259 |
access = _PackAccess({}) |
|
260 |
transport = self.get_transport() |
|
261 |
packname = 'packfile' |
|
262 |
index = 'foo' |
|
263 |
def write_data(bytes): |
|
264 |
transport.append_bytes(packname, bytes) |
|
265 |
writer = pack.ContainerWriter(write_data) |
|
266 |
writer.begin() |
|
267 |
access.set_writer(writer, index, (transport, packname)) |
|
268 |
memos = access.add_raw_records([10], '1234567890') |
|
269 |
writer.end() |
|
270 |
self.assertEqual(['1234567890'], list(access.get_raw_records(memos))) |
|
271 |
||
272 |
||
2329.1.1
by John Arbash Meinel
Update _KnitData parser to raise more helpful errors when it detects corruption. |
273 |
class LowLevelKnitDataTests(TestCase): |
274 |
||
275 |
def create_gz_content(self, text): |
|
276 |
sio = StringIO() |
|
277 |
gz_file = gzip.GzipFile(mode='wb', fileobj=sio) |
|
278 |
gz_file.write(text) |
|
279 |
gz_file.close() |
|
280 |
return sio.getvalue() |
|
281 |
||
282 |
def test_valid_knit_data(self): |
|
283 |
sha1sum = sha.new('foo\nbar\n').hexdigest() |
|
284 |
gz_txt = self.create_gz_content('version rev-id-1 2 %s\n' |
|
285 |
'foo\n' |
|
286 |
'bar\n' |
|
287 |
'end rev-id-1\n' |
|
288 |
% (sha1sum,)) |
|
289 |
transport = MockTransport([gz_txt]) |
|
2670.2.2
by Robert Collins
* In ``bzrlib.knit`` the internal interface has been altered to use |
290 |
access = _KnitAccess(transport, 'filename', None, None, False, False) |
291 |
data = _KnitData(access=access) |
|
292 |
records = [('rev-id-1', (None, 0, len(gz_txt)))] |
|
2329.1.1
by John Arbash Meinel
Update _KnitData parser to raise more helpful errors when it detects corruption. |
293 |
|
294 |
contents = data.read_records(records) |
|
295 |
self.assertEqual({'rev-id-1':(['foo\n', 'bar\n'], sha1sum)}, contents) |
|
296 |
||
297 |
raw_contents = list(data.read_records_iter_raw(records)) |
|
298 |
self.assertEqual([('rev-id-1', gz_txt)], raw_contents) |
|
299 |
||
300 |
def test_not_enough_lines(self): |
|
301 |
sha1sum = sha.new('foo\n').hexdigest() |
|
302 |
# record says 2 lines data says 1
|
|
303 |
gz_txt = self.create_gz_content('version rev-id-1 2 %s\n' |
|
304 |
'foo\n' |
|
305 |
'end rev-id-1\n' |
|
306 |
% (sha1sum,)) |
|
307 |
transport = MockTransport([gz_txt]) |
|
2670.2.2
by Robert Collins
* In ``bzrlib.knit`` the internal interface has been altered to use |
308 |
access = _KnitAccess(transport, 'filename', None, None, False, False) |
309 |
data = _KnitData(access=access) |
|
310 |
records = [('rev-id-1', (None, 0, len(gz_txt)))] |
|
2329.1.1
by John Arbash Meinel
Update _KnitData parser to raise more helpful errors when it detects corruption. |
311 |
self.assertRaises(errors.KnitCorrupt, data.read_records, records) |
312 |
||
313 |
# read_records_iter_raw won't detect that sort of mismatch/corruption
|
|
314 |
raw_contents = list(data.read_records_iter_raw(records)) |
|
315 |
self.assertEqual([('rev-id-1', gz_txt)], raw_contents) |
|
316 |
||
317 |
def test_too_many_lines(self): |
|
318 |
sha1sum = sha.new('foo\nbar\n').hexdigest() |
|
319 |
# record says 1 lines data says 2
|
|
320 |
gz_txt = self.create_gz_content('version rev-id-1 1 %s\n' |
|
321 |
'foo\n' |
|
322 |
'bar\n' |
|
323 |
'end rev-id-1\n' |
|
324 |
% (sha1sum,)) |
|
325 |
transport = MockTransport([gz_txt]) |
|
2670.2.2
by Robert Collins
* In ``bzrlib.knit`` the internal interface has been altered to use |
326 |
access = _KnitAccess(transport, 'filename', None, None, False, False) |
327 |
data = _KnitData(access=access) |
|
328 |
records = [('rev-id-1', (None, 0, len(gz_txt)))] |
|
2329.1.1
by John Arbash Meinel
Update _KnitData parser to raise more helpful errors when it detects corruption. |
329 |
self.assertRaises(errors.KnitCorrupt, data.read_records, records) |
330 |
||
331 |
# read_records_iter_raw won't detect that sort of mismatch/corruption
|
|
332 |
raw_contents = list(data.read_records_iter_raw(records)) |
|
333 |
self.assertEqual([('rev-id-1', gz_txt)], raw_contents) |
|
334 |
||
335 |
def test_mismatched_version_id(self): |
|
336 |
sha1sum = sha.new('foo\nbar\n').hexdigest() |
|
337 |
gz_txt = self.create_gz_content('version rev-id-1 2 %s\n' |
|
338 |
'foo\n' |
|
339 |
'bar\n' |
|
340 |
'end rev-id-1\n' |
|
341 |
% (sha1sum,)) |
|
342 |
transport = MockTransport([gz_txt]) |
|
2670.2.2
by Robert Collins
* In ``bzrlib.knit`` the internal interface has been altered to use |
343 |
access = _KnitAccess(transport, 'filename', None, None, False, False) |
344 |
data = _KnitData(access=access) |
|
2329.1.1
by John Arbash Meinel
Update _KnitData parser to raise more helpful errors when it detects corruption. |
345 |
# We are asking for rev-id-2, but the data is rev-id-1
|
2670.2.2
by Robert Collins
* In ``bzrlib.knit`` the internal interface has been altered to use |
346 |
records = [('rev-id-2', (None, 0, len(gz_txt)))] |
2329.1.1
by John Arbash Meinel
Update _KnitData parser to raise more helpful errors when it detects corruption. |
347 |
self.assertRaises(errors.KnitCorrupt, data.read_records, records) |
348 |
||
349 |
# read_records_iter_raw will notice if we request the wrong version.
|
|
350 |
self.assertRaises(errors.KnitCorrupt, list, |
|
351 |
data.read_records_iter_raw(records)) |
|
352 |
||
353 |
def test_uncompressed_data(self): |
|
354 |
sha1sum = sha.new('foo\nbar\n').hexdigest() |
|
355 |
txt = ('version rev-id-1 2 %s\n' |
|
356 |
'foo\n' |
|
357 |
'bar\n' |
|
358 |
'end rev-id-1\n' |
|
359 |
% (sha1sum,)) |
|
360 |
transport = MockTransport([txt]) |
|
2670.2.2
by Robert Collins
* In ``bzrlib.knit`` the internal interface has been altered to use |
361 |
access = _KnitAccess(transport, 'filename', None, None, False, False) |
362 |
data = _KnitData(access=access) |
|
363 |
records = [('rev-id-1', (None, 0, len(txt)))] |
|
2329.1.1
by John Arbash Meinel
Update _KnitData parser to raise more helpful errors when it detects corruption. |
364 |
|
365 |
# We don't have valid gzip data ==> corrupt
|
|
366 |
self.assertRaises(errors.KnitCorrupt, data.read_records, records) |
|
367 |
||
368 |
# read_records_iter_raw will notice the bad data
|
|
369 |
self.assertRaises(errors.KnitCorrupt, list, |
|
370 |
data.read_records_iter_raw(records)) |
|
371 |
||
372 |
def test_corrupted_data(self): |
|
373 |
sha1sum = sha.new('foo\nbar\n').hexdigest() |
|
374 |
gz_txt = self.create_gz_content('version rev-id-1 2 %s\n' |
|
375 |
'foo\n' |
|
376 |
'bar\n' |
|
377 |
'end rev-id-1\n' |
|
378 |
% (sha1sum,)) |
|
379 |
# Change 2 bytes in the middle to \xff
|
|
380 |
gz_txt = gz_txt[:10] + '\xff\xff' + gz_txt[12:] |
|
381 |
transport = MockTransport([gz_txt]) |
|
2670.2.2
by Robert Collins
* In ``bzrlib.knit`` the internal interface has been altered to use |
382 |
access = _KnitAccess(transport, 'filename', None, None, False, False) |
383 |
data = _KnitData(access=access) |
|
384 |
records = [('rev-id-1', (None, 0, len(gz_txt)))] |
|
2329.1.1
by John Arbash Meinel
Update _KnitData parser to raise more helpful errors when it detects corruption. |
385 |
|
386 |
self.assertRaises(errors.KnitCorrupt, data.read_records, records) |
|
387 |
||
388 |
# read_records_iter_raw will notice if we request the wrong version.
|
|
389 |
self.assertRaises(errors.KnitCorrupt, list, |
|
390 |
data.read_records_iter_raw(records)) |
|
391 |
||
392 |
||
2158.3.1
by Dmitry Vasiliev
KnitIndex tests/fixes/optimizations |
393 |
class LowLevelKnitIndexTests(TestCase): |
394 |
||
2484.1.1
by John Arbash Meinel
Add an initial function to read knit indexes in pyrex. |
395 |
def get_knit_index(self, *args, **kwargs): |
396 |
orig = knit._load_data |
|
397 |
def reset(): |
|
398 |
knit._load_data = orig |
|
399 |
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 |
400 |
from bzrlib._knit_load_data_py import _load_data_py |
401 |
knit._load_data = _load_data_py |
|
2484.1.1
by John Arbash Meinel
Add an initial function to read knit indexes in pyrex. |
402 |
return _KnitIndex(*args, **kwargs) |
403 |
||
2158.3.1
by Dmitry Vasiliev
KnitIndex tests/fixes/optimizations |
404 |
def test_no_such_file(self): |
405 |
transport = MockTransport() |
|
406 |
||
2484.1.1
by John Arbash Meinel
Add an initial function to read knit indexes in pyrex. |
407 |
self.assertRaises(NoSuchFile, self.get_knit_index, |
408 |
transport, "filename", "r") |
|
409 |
self.assertRaises(NoSuchFile, self.get_knit_index, |
|
410 |
transport, "filename", "w", create=False) |
|
2158.3.1
by Dmitry Vasiliev
KnitIndex tests/fixes/optimizations |
411 |
|
412 |
def test_create_file(self): |
|
413 |
transport = MockTransport() |
|
414 |
||
2484.1.1
by John Arbash Meinel
Add an initial function to read knit indexes in pyrex. |
415 |
index = self.get_knit_index(transport, "filename", "w", |
2158.3.1
by Dmitry Vasiliev
KnitIndex tests/fixes/optimizations |
416 |
file_mode="wb", create=True) |
417 |
self.assertEqual( |
|
418 |
("put_bytes_non_atomic", |
|
419 |
("filename", index.HEADER), {"mode": "wb"}), |
|
420 |
transport.calls.pop(0)) |
|
421 |
||
422 |
def test_delay_create_file(self): |
|
423 |
transport = MockTransport() |
|
424 |
||
2484.1.1
by John Arbash Meinel
Add an initial function to read knit indexes in pyrex. |
425 |
index = self.get_knit_index(transport, "filename", "w", |
2158.3.1
by Dmitry Vasiliev
KnitIndex tests/fixes/optimizations |
426 |
create=True, file_mode="wb", create_parent_dir=True, |
427 |
delay_create=True, dir_mode=0777) |
|
428 |
self.assertEqual([], transport.calls) |
|
429 |
||
430 |
index.add_versions([]) |
|
431 |
name, (filename, f), kwargs = transport.calls.pop(0) |
|
432 |
self.assertEqual("put_file_non_atomic", name) |
|
433 |
self.assertEqual( |
|
434 |
{"dir_mode": 0777, "create_parent_dir": True, "mode": "wb"}, |
|
435 |
kwargs) |
|
436 |
self.assertEqual("filename", filename) |
|
437 |
self.assertEqual(index.HEADER, f.read()) |
|
438 |
||
439 |
index.add_versions([]) |
|
440 |
self.assertEqual(("append_bytes", ("filename", ""), {}), |
|
441 |
transport.calls.pop(0)) |
|
442 |
||
443 |
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 |
444 |
unicode_revision_id = u"version-\N{CYRILLIC CAPITAL LETTER A}" |
445 |
utf8_revision_id = unicode_revision_id.encode('utf-8') |
|
2158.3.1
by Dmitry Vasiliev
KnitIndex tests/fixes/optimizations |
446 |
transport = MockTransport([ |
447 |
_KnitIndex.HEADER, |
|
2249.5.12
by John Arbash Meinel
Change the APIs for VersionedFile, Store, and some of Repository into utf-8 |
448 |
'%s option 0 1 :' % (utf8_revision_id,) |
2158.3.1
by Dmitry Vasiliev
KnitIndex tests/fixes/optimizations |
449 |
])
|
2484.1.1
by John Arbash Meinel
Add an initial function to read knit indexes in pyrex. |
450 |
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 |
451 |
# _KnitIndex is a private class, and deals in utf8 revision_ids, not
|
452 |
# Unicode revision_ids.
|
|
453 |
self.assertTrue(index.has_version(utf8_revision_id)) |
|
454 |
self.assertFalse(index.has_version(unicode_revision_id)) |
|
2158.3.1
by Dmitry Vasiliev
KnitIndex tests/fixes/optimizations |
455 |
|
456 |
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 |
457 |
unicode_revision_id = u"version-\N{CYRILLIC CAPITAL LETTER A}" |
458 |
utf8_revision_id = unicode_revision_id.encode('utf-8') |
|
2158.3.1
by Dmitry Vasiliev
KnitIndex tests/fixes/optimizations |
459 |
transport = MockTransport([ |
460 |
_KnitIndex.HEADER, |
|
2249.5.12
by John Arbash Meinel
Change the APIs for VersionedFile, Store, and some of Repository into utf-8 |
461 |
"version option 0 1 .%s :" % (utf8_revision_id,) |
2158.3.1
by Dmitry Vasiliev
KnitIndex tests/fixes/optimizations |
462 |
])
|
2484.1.1
by John Arbash Meinel
Add an initial function to read knit indexes in pyrex. |
463 |
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 |
464 |
self.assertEqual([utf8_revision_id], |
2158.3.1
by Dmitry Vasiliev
KnitIndex tests/fixes/optimizations |
465 |
index.get_parents_with_ghosts("version")) |
466 |
||
467 |
def test_read_ignore_corrupted_lines(self): |
|
468 |
transport = MockTransport([ |
|
469 |
_KnitIndex.HEADER, |
|
470 |
"corrupted", |
|
471 |
"corrupted options 0 1 .b .c ", |
|
472 |
"version options 0 1 :"
|
|
473 |
])
|
|
2484.1.1
by John Arbash Meinel
Add an initial function to read knit indexes in pyrex. |
474 |
index = self.get_knit_index(transport, "filename", "r") |
2158.3.1
by Dmitry Vasiliev
KnitIndex tests/fixes/optimizations |
475 |
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 |
476 |
self.assertTrue(index.has_version("version")) |
2158.3.1
by Dmitry Vasiliev
KnitIndex tests/fixes/optimizations |
477 |
|
478 |
def test_read_corrupted_header(self): |
|
2196.2.3
by John Arbash Meinel
Update tests and code to pass after merging bzr.dev |
479 |
transport = MockTransport(['not a bzr knit index header\n']) |
2158.3.1
by Dmitry Vasiliev
KnitIndex tests/fixes/optimizations |
480 |
self.assertRaises(KnitHeaderError, |
2484.1.1
by John Arbash Meinel
Add an initial function to read knit indexes in pyrex. |
481 |
self.get_knit_index, transport, "filename", "r") |
2158.3.1
by Dmitry Vasiliev
KnitIndex tests/fixes/optimizations |
482 |
|
483 |
def test_read_duplicate_entries(self): |
|
484 |
transport = MockTransport([ |
|
485 |
_KnitIndex.HEADER, |
|
486 |
"parent options 0 1 :", |
|
487 |
"version options1 0 1 0 :", |
|
488 |
"version options2 1 2 .other :", |
|
489 |
"version options3 3 4 0 .other :"
|
|
490 |
])
|
|
2484.1.1
by John Arbash Meinel
Add an initial function to read knit indexes in pyrex. |
491 |
index = self.get_knit_index(transport, "filename", "r") |
2158.3.1
by Dmitry Vasiliev
KnitIndex tests/fixes/optimizations |
492 |
self.assertEqual(2, index.num_versions()) |
2625.8.1
by Robert Collins
LIBRARY API BREAKS: |
493 |
# check that the index used is the first one written. (Specific
|
494 |
# to KnitIndex style indices.
|
|
495 |
self.assertEqual("1", index._version_list_to_index(["version"])) |
|
2670.2.2
by Robert Collins
* In ``bzrlib.knit`` the internal interface has been altered to use |
496 |
self.assertEqual((None, 3, 4), index.get_position("version")) |
2249.5.12
by John Arbash Meinel
Change the APIs for VersionedFile, Store, and some of Repository into utf-8 |
497 |
self.assertEqual(["options3"], index.get_options("version")) |
498 |
self.assertEqual(["parent", "other"], |
|
499 |
index.get_parents_with_ghosts("version")) |
|
2158.3.1
by Dmitry Vasiliev
KnitIndex tests/fixes/optimizations |
500 |
|
501 |
def test_read_compressed_parents(self): |
|
502 |
transport = MockTransport([ |
|
503 |
_KnitIndex.HEADER, |
|
504 |
"a option 0 1 :", |
|
505 |
"b option 0 1 0 :", |
|
506 |
"c option 0 1 1 0 :", |
|
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") |
2249.5.12
by John Arbash Meinel
Change the APIs for VersionedFile, Store, and some of Repository into utf-8 |
509 |
self.assertEqual(["a"], index.get_parents("b")) |
510 |
self.assertEqual(["b", "a"], index.get_parents("c")) |
|
2158.3.1
by Dmitry Vasiliev
KnitIndex tests/fixes/optimizations |
511 |
|
512 |
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 |
513 |
unicode_revision_id = u"version-\N{CYRILLIC CAPITAL LETTER A}" |
514 |
utf8_revision_id = unicode_revision_id.encode('utf-8') |
|
2158.3.1
by Dmitry Vasiliev
KnitIndex tests/fixes/optimizations |
515 |
transport = MockTransport([ |
516 |
_KnitIndex.HEADER |
|
517 |
])
|
|
2484.1.1
by John Arbash Meinel
Add an initial function to read knit indexes in pyrex. |
518 |
index = self.get_knit_index(transport, "filename", "r") |
2670.2.2
by Robert Collins
* In ``bzrlib.knit`` the internal interface has been altered to use |
519 |
index.add_version(utf8_revision_id, ["option"], (None, 0, 1), []) |
2158.3.1
by Dmitry Vasiliev
KnitIndex tests/fixes/optimizations |
520 |
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 |
521 |
"\n%s option 0 1 :" % (utf8_revision_id,)), |
2158.3.1
by Dmitry Vasiliev
KnitIndex tests/fixes/optimizations |
522 |
{}),
|
523 |
transport.calls.pop(0)) |
|
524 |
||
525 |
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 |
526 |
unicode_revision_id = u"version-\N{CYRILLIC CAPITAL LETTER A}" |
527 |
utf8_revision_id = unicode_revision_id.encode('utf-8') |
|
2158.3.1
by Dmitry Vasiliev
KnitIndex tests/fixes/optimizations |
528 |
transport = MockTransport([ |
529 |
_KnitIndex.HEADER |
|
530 |
])
|
|
2484.1.1
by John Arbash Meinel
Add an initial function to read knit indexes in pyrex. |
531 |
index = self.get_knit_index(transport, "filename", "r") |
2670.2.2
by Robert Collins
* In ``bzrlib.knit`` the internal interface has been altered to use |
532 |
index.add_version("version", ["option"], (None, 0, 1), [utf8_revision_id]) |
2158.3.1
by Dmitry Vasiliev
KnitIndex tests/fixes/optimizations |
533 |
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 |
534 |
"\nversion option 0 1 .%s :" % (utf8_revision_id,)), |
2158.3.1
by Dmitry Vasiliev
KnitIndex tests/fixes/optimizations |
535 |
{}),
|
536 |
transport.calls.pop(0)) |
|
537 |
||
538 |
def test_get_graph(self): |
|
539 |
transport = MockTransport() |
|
2484.1.1
by John Arbash Meinel
Add an initial function to read knit indexes in pyrex. |
540 |
index = self.get_knit_index(transport, "filename", "w", create=True) |
2158.3.1
by Dmitry Vasiliev
KnitIndex tests/fixes/optimizations |
541 |
self.assertEqual([], index.get_graph()) |
542 |
||
2670.2.2
by Robert Collins
* In ``bzrlib.knit`` the internal interface has been altered to use |
543 |
index.add_version("a", ["option"], (None, 0, 1), ["b"]) |
2249.5.12
by John Arbash Meinel
Change the APIs for VersionedFile, Store, and some of Repository into utf-8 |
544 |
self.assertEqual([("a", ["b"])], index.get_graph()) |
2158.3.1
by Dmitry Vasiliev
KnitIndex tests/fixes/optimizations |
545 |
|
2670.2.2
by Robert Collins
* In ``bzrlib.knit`` the internal interface has been altered to use |
546 |
index.add_version("c", ["option"], (None, 0, 1), ["d"]) |
2249.5.12
by John Arbash Meinel
Change the APIs for VersionedFile, Store, and some of Repository into utf-8 |
547 |
self.assertEqual([("a", ["b"]), ("c", ["d"])], |
2158.3.1
by Dmitry Vasiliev
KnitIndex tests/fixes/optimizations |
548 |
sorted(index.get_graph())) |
549 |
||
550 |
def test_get_ancestry(self): |
|
551 |
transport = MockTransport([ |
|
552 |
_KnitIndex.HEADER, |
|
553 |
"a option 0 1 :", |
|
554 |
"b option 0 1 0 .e :", |
|
555 |
"c option 0 1 1 0 :", |
|
556 |
"d option 0 1 2 .f :"
|
|
557 |
])
|
|
2484.1.1
by John Arbash Meinel
Add an initial function to read knit indexes in pyrex. |
558 |
index = self.get_knit_index(transport, "filename", "r") |
2158.3.1
by Dmitry Vasiliev
KnitIndex tests/fixes/optimizations |
559 |
|
560 |
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 |
561 |
self.assertEqual(["a"], index.get_ancestry(["a"])) |
562 |
self.assertEqual(["a", "b"], index.get_ancestry(["b"])) |
|
563 |
self.assertEqual(["a", "b", "c"], index.get_ancestry(["c"])) |
|
564 |
self.assertEqual(["a", "b", "c", "d"], index.get_ancestry(["d"])) |
|
565 |
self.assertEqual(["a", "b"], index.get_ancestry(["a", "b"])) |
|
566 |
self.assertEqual(["a", "b", "c"], index.get_ancestry(["a", "c"])) |
|
2158.3.1
by Dmitry Vasiliev
KnitIndex tests/fixes/optimizations |
567 |
|
2249.5.12
by John Arbash Meinel
Change the APIs for VersionedFile, Store, and some of Repository into utf-8 |
568 |
self.assertRaises(RevisionNotPresent, index.get_ancestry, ["e"]) |
2158.3.1
by Dmitry Vasiliev
KnitIndex tests/fixes/optimizations |
569 |
|
570 |
def test_get_ancestry_with_ghosts(self): |
|
571 |
transport = MockTransport([ |
|
572 |
_KnitIndex.HEADER, |
|
573 |
"a option 0 1 :", |
|
574 |
"b option 0 1 0 .e :", |
|
575 |
"c option 0 1 0 .f .g :", |
|
576 |
"d option 0 1 2 .h .j .k :"
|
|
577 |
])
|
|
2484.1.1
by John Arbash Meinel
Add an initial function to read knit indexes in pyrex. |
578 |
index = self.get_knit_index(transport, "filename", "r") |
2158.3.1
by Dmitry Vasiliev
KnitIndex tests/fixes/optimizations |
579 |
|
580 |
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 |
581 |
self.assertEqual(["a"], index.get_ancestry_with_ghosts(["a"])) |
582 |
self.assertEqual(["a", "e", "b"], |
|
583 |
index.get_ancestry_with_ghosts(["b"])) |
|
584 |
self.assertEqual(["a", "g", "f", "c"], |
|
585 |
index.get_ancestry_with_ghosts(["c"])) |
|
586 |
self.assertEqual(["a", "g", "f", "c", "k", "j", "h", "d"], |
|
587 |
index.get_ancestry_with_ghosts(["d"])) |
|
588 |
self.assertEqual(["a", "e", "b"], |
|
589 |
index.get_ancestry_with_ghosts(["a", "b"])) |
|
590 |
self.assertEqual(["a", "g", "f", "c"], |
|
591 |
index.get_ancestry_with_ghosts(["a", "c"])) |
|
2158.3.1
by Dmitry Vasiliev
KnitIndex tests/fixes/optimizations |
592 |
self.assertEqual( |
2249.5.12
by John Arbash Meinel
Change the APIs for VersionedFile, Store, and some of Repository into utf-8 |
593 |
["a", "g", "f", "c", "e", "b", "k", "j", "h", "d"], |
594 |
index.get_ancestry_with_ghosts(["b", "d"])) |
|
2158.3.1
by Dmitry Vasiliev
KnitIndex tests/fixes/optimizations |
595 |
|
596 |
self.assertRaises(RevisionNotPresent, |
|
2249.5.12
by John Arbash Meinel
Change the APIs for VersionedFile, Store, and some of Repository into utf-8 |
597 |
index.get_ancestry_with_ghosts, ["e"]) |
2158.3.1
by Dmitry Vasiliev
KnitIndex tests/fixes/optimizations |
598 |
|
2625.8.1
by Robert Collins
LIBRARY API BREAKS: |
599 |
def test_iter_parents(self): |
600 |
transport = MockTransport() |
|
601 |
index = self.get_knit_index(transport, "filename", "w", create=True) |
|
602 |
# no parents
|
|
2670.2.2
by Robert Collins
* In ``bzrlib.knit`` the internal interface has been altered to use |
603 |
index.add_version('r0', ['option'], (None, 0, 1), []) |
2625.8.1
by Robert Collins
LIBRARY API BREAKS: |
604 |
# 1 parent
|
2670.2.2
by Robert Collins
* In ``bzrlib.knit`` the internal interface has been altered to use |
605 |
index.add_version('r1', ['option'], (None, 0, 1), ['r0']) |
2625.8.1
by Robert Collins
LIBRARY API BREAKS: |
606 |
# 2 parents
|
2670.2.2
by Robert Collins
* In ``bzrlib.knit`` the internal interface has been altered to use |
607 |
index.add_version('r2', ['option'], (None, 0, 1), ['r1', 'r0']) |
2625.8.1
by Robert Collins
LIBRARY API BREAKS: |
608 |
# XXX TODO a ghost
|
609 |
# cases: each sample data individually:
|
|
610 |
self.assertEqual(set([('r0', ())]), |
|
611 |
set(index.iter_parents(['r0']))) |
|
612 |
self.assertEqual(set([('r1', ('r0', ))]), |
|
613 |
set(index.iter_parents(['r1']))) |
|
614 |
self.assertEqual(set([('r2', ('r1', 'r0'))]), |
|
615 |
set(index.iter_parents(['r2']))) |
|
616 |
# no nodes returned for a missing node
|
|
617 |
self.assertEqual(set(), |
|
618 |
set(index.iter_parents(['missing']))) |
|
619 |
# 1 node returned with missing nodes skipped
|
|
620 |
self.assertEqual(set([('r1', ('r0', ))]), |
|
621 |
set(index.iter_parents(['ghost1', 'r1', 'ghost']))) |
|
622 |
# 2 nodes returned
|
|
623 |
self.assertEqual(set([('r0', ()), ('r1', ('r0', ))]), |
|
624 |
set(index.iter_parents(['r0', 'r1']))) |
|
625 |
# 2 nodes returned, missing skipped
|
|
626 |
self.assertEqual(set([('r0', ()), ('r1', ('r0', ))]), |
|
627 |
set(index.iter_parents(['a', 'r0', 'b', 'r1', 'c']))) |
|
628 |
||
2158.3.1
by Dmitry Vasiliev
KnitIndex tests/fixes/optimizations |
629 |
def test_num_versions(self): |
630 |
transport = MockTransport([ |
|
631 |
_KnitIndex.HEADER |
|
632 |
])
|
|
2484.1.1
by John Arbash Meinel
Add an initial function to read knit indexes in pyrex. |
633 |
index = self.get_knit_index(transport, "filename", "r") |
2158.3.1
by Dmitry Vasiliev
KnitIndex tests/fixes/optimizations |
634 |
|
635 |
self.assertEqual(0, index.num_versions()) |
|
636 |
self.assertEqual(0, len(index)) |
|
637 |
||
2670.2.2
by Robert Collins
* In ``bzrlib.knit`` the internal interface has been altered to use |
638 |
index.add_version("a", ["option"], (None, 0, 1), []) |
639 |
self.assertEqual(1, index.num_versions()) |
|
640 |
self.assertEqual(1, len(index)) |
|
641 |
||
642 |
index.add_version("a", ["option2"], (None, 1, 2), []) |
|
643 |
self.assertEqual(1, index.num_versions()) |
|
644 |
self.assertEqual(1, len(index)) |
|
645 |
||
646 |
index.add_version("b", ["option"], (None, 0, 1), []) |
|
2158.3.1
by Dmitry Vasiliev
KnitIndex tests/fixes/optimizations |
647 |
self.assertEqual(2, index.num_versions()) |
648 |
self.assertEqual(2, len(index)) |
|
649 |
||
650 |
def test_get_versions(self): |
|
651 |
transport = MockTransport([ |
|
652 |
_KnitIndex.HEADER |
|
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 |
|
656 |
self.assertEqual([], index.get_versions()) |
|
657 |
||
2670.2.2
by Robert Collins
* In ``bzrlib.knit`` the internal interface has been altered to use |
658 |
index.add_version("a", ["option"], (None, 0, 1), []) |
659 |
self.assertEqual(["a"], index.get_versions()) |
|
660 |
||
661 |
index.add_version("a", ["option"], (None, 0, 1), []) |
|
662 |
self.assertEqual(["a"], index.get_versions()) |
|
663 |
||
664 |
index.add_version("b", ["option"], (None, 0, 1), []) |
|
2249.5.12
by John Arbash Meinel
Change the APIs for VersionedFile, Store, and some of Repository into utf-8 |
665 |
self.assertEqual(["a", "b"], index.get_versions()) |
2158.3.1
by Dmitry Vasiliev
KnitIndex tests/fixes/optimizations |
666 |
|
667 |
def test_add_version(self): |
|
668 |
transport = MockTransport([ |
|
669 |
_KnitIndex.HEADER |
|
670 |
])
|
|
2484.1.1
by John Arbash Meinel
Add an initial function to read knit indexes in pyrex. |
671 |
index = self.get_knit_index(transport, "filename", "r") |
2158.3.1
by Dmitry Vasiliev
KnitIndex tests/fixes/optimizations |
672 |
|
2670.2.2
by Robert Collins
* In ``bzrlib.knit`` the internal interface has been altered to use |
673 |
index.add_version("a", ["option"], (None, 0, 1), ["b"]) |
2158.3.1
by Dmitry Vasiliev
KnitIndex tests/fixes/optimizations |
674 |
self.assertEqual(("append_bytes", |
675 |
("filename", "\na option 0 1 .b :"), |
|
676 |
{}), transport.calls.pop(0)) |
|
2249.5.12
by John Arbash Meinel
Change the APIs for VersionedFile, Store, and some of Repository into utf-8 |
677 |
self.assertTrue(index.has_version("a")) |
2158.3.1
by Dmitry Vasiliev
KnitIndex tests/fixes/optimizations |
678 |
self.assertEqual(1, index.num_versions()) |
2670.2.2
by Robert Collins
* In ``bzrlib.knit`` the internal interface has been altered to use |
679 |
self.assertEqual((None, 0, 1), index.get_position("a")) |
2249.5.12
by John Arbash Meinel
Change the APIs for VersionedFile, Store, and some of Repository into utf-8 |
680 |
self.assertEqual(["option"], index.get_options("a")) |
681 |
self.assertEqual(["b"], index.get_parents_with_ghosts("a")) |
|
2158.3.1
by Dmitry Vasiliev
KnitIndex tests/fixes/optimizations |
682 |
|
2670.2.2
by Robert Collins
* In ``bzrlib.knit`` the internal interface has been altered to use |
683 |
index.add_version("a", ["opt"], (None, 1, 2), ["c"]) |
2158.3.1
by Dmitry Vasiliev
KnitIndex tests/fixes/optimizations |
684 |
self.assertEqual(("append_bytes", |
685 |
("filename", "\na opt 1 2 .c :"), |
|
686 |
{}), transport.calls.pop(0)) |
|
2249.5.12
by John Arbash Meinel
Change the APIs for VersionedFile, Store, and some of Repository into utf-8 |
687 |
self.assertTrue(index.has_version("a")) |
2158.3.1
by Dmitry Vasiliev
KnitIndex tests/fixes/optimizations |
688 |
self.assertEqual(1, index.num_versions()) |
2670.2.2
by Robert Collins
* In ``bzrlib.knit`` the internal interface has been altered to use |
689 |
self.assertEqual((None, 1, 2), index.get_position("a")) |
2249.5.12
by John Arbash Meinel
Change the APIs for VersionedFile, Store, and some of Repository into utf-8 |
690 |
self.assertEqual(["opt"], index.get_options("a")) |
691 |
self.assertEqual(["c"], index.get_parents_with_ghosts("a")) |
|
2158.3.1
by Dmitry Vasiliev
KnitIndex tests/fixes/optimizations |
692 |
|
2670.2.2
by Robert Collins
* In ``bzrlib.knit`` the internal interface has been altered to use |
693 |
index.add_version("b", ["option"], (None, 2, 3), ["a"]) |
2158.3.1
by Dmitry Vasiliev
KnitIndex tests/fixes/optimizations |
694 |
self.assertEqual(("append_bytes", |
695 |
("filename", "\nb option 2 3 0 :"), |
|
696 |
{}), transport.calls.pop(0)) |
|
2249.5.12
by John Arbash Meinel
Change the APIs for VersionedFile, Store, and some of Repository into utf-8 |
697 |
self.assertTrue(index.has_version("b")) |
2158.3.1
by Dmitry Vasiliev
KnitIndex tests/fixes/optimizations |
698 |
self.assertEqual(2, index.num_versions()) |
2670.2.2
by Robert Collins
* In ``bzrlib.knit`` the internal interface has been altered to use |
699 |
self.assertEqual((None, 2, 3), index.get_position("b")) |
2249.5.12
by John Arbash Meinel
Change the APIs for VersionedFile, Store, and some of Repository into utf-8 |
700 |
self.assertEqual(["option"], index.get_options("b")) |
701 |
self.assertEqual(["a"], index.get_parents_with_ghosts("b")) |
|
2158.3.1
by Dmitry Vasiliev
KnitIndex tests/fixes/optimizations |
702 |
|
703 |
def test_add_versions(self): |
|
704 |
transport = MockTransport([ |
|
705 |
_KnitIndex.HEADER |
|
706 |
])
|
|
2484.1.1
by John Arbash Meinel
Add an initial function to read knit indexes in pyrex. |
707 |
index = self.get_knit_index(transport, "filename", "r") |
2158.3.1
by Dmitry Vasiliev
KnitIndex tests/fixes/optimizations |
708 |
|
709 |
index.add_versions([ |
|
2670.2.2
by Robert Collins
* In ``bzrlib.knit`` the internal interface has been altered to use |
710 |
("a", ["option"], (None, 0, 1), ["b"]), |
711 |
("a", ["opt"], (None, 1, 2), ["c"]), |
|
712 |
("b", ["option"], (None, 2, 3), ["a"]) |
|
2158.3.1
by Dmitry Vasiliev
KnitIndex tests/fixes/optimizations |
713 |
])
|
714 |
self.assertEqual(("append_bytes", ("filename", |
|
715 |
"\na option 0 1 .b :" |
|
716 |
"\na opt 1 2 .c :" |
|
717 |
"\nb option 2 3 0 :" |
|
718 |
), {}), transport.calls.pop(0)) |
|
2249.5.12
by John Arbash Meinel
Change the APIs for VersionedFile, Store, and some of Repository into utf-8 |
719 |
self.assertTrue(index.has_version("a")) |
720 |
self.assertTrue(index.has_version("b")) |
|
2158.3.1
by Dmitry Vasiliev
KnitIndex tests/fixes/optimizations |
721 |
self.assertEqual(2, index.num_versions()) |
2670.2.2
by Robert Collins
* In ``bzrlib.knit`` the internal interface has been altered to use |
722 |
self.assertEqual((None, 1, 2), index.get_position("a")) |
723 |
self.assertEqual((None, 2, 3), index.get_position("b")) |
|
2249.5.12
by John Arbash Meinel
Change the APIs for VersionedFile, Store, and some of Repository into utf-8 |
724 |
self.assertEqual(["opt"], index.get_options("a")) |
725 |
self.assertEqual(["option"], index.get_options("b")) |
|
726 |
self.assertEqual(["c"], index.get_parents_with_ghosts("a")) |
|
727 |
self.assertEqual(["a"], index.get_parents_with_ghosts("b")) |
|
2158.3.1
by Dmitry Vasiliev
KnitIndex tests/fixes/optimizations |
728 |
|
729 |
def test_delay_create_and_add_versions(self): |
|
730 |
transport = MockTransport() |
|
731 |
||
2484.1.1
by John Arbash Meinel
Add an initial function to read knit indexes in pyrex. |
732 |
index = self.get_knit_index(transport, "filename", "w", |
2158.3.1
by Dmitry Vasiliev
KnitIndex tests/fixes/optimizations |
733 |
create=True, file_mode="wb", create_parent_dir=True, |
734 |
delay_create=True, dir_mode=0777) |
|
735 |
self.assertEqual([], transport.calls) |
|
736 |
||
737 |
index.add_versions([ |
|
2670.2.2
by Robert Collins
* In ``bzrlib.knit`` the internal interface has been altered to use |
738 |
("a", ["option"], (None, 0, 1), ["b"]), |
739 |
("a", ["opt"], (None, 1, 2), ["c"]), |
|
740 |
("b", ["option"], (None, 2, 3), ["a"]) |
|
2158.3.1
by Dmitry Vasiliev
KnitIndex tests/fixes/optimizations |
741 |
])
|
742 |
name, (filename, f), kwargs = transport.calls.pop(0) |
|
743 |
self.assertEqual("put_file_non_atomic", name) |
|
744 |
self.assertEqual( |
|
745 |
{"dir_mode": 0777, "create_parent_dir": True, "mode": "wb"}, |
|
746 |
kwargs) |
|
747 |
self.assertEqual("filename", filename) |
|
748 |
self.assertEqual( |
|
749 |
index.HEADER + |
|
750 |
"\na option 0 1 .b :" |
|
751 |
"\na opt 1 2 .c :" |
|
752 |
"\nb option 2 3 0 :", |
|
753 |
f.read()) |
|
754 |
||
755 |
def test_has_version(self): |
|
756 |
transport = MockTransport([ |
|
757 |
_KnitIndex.HEADER, |
|
758 |
"a option 0 1 :"
|
|
759 |
])
|
|
2484.1.1
by John Arbash Meinel
Add an initial function to read knit indexes in pyrex. |
760 |
index = self.get_knit_index(transport, "filename", "r") |
2158.3.1
by Dmitry Vasiliev
KnitIndex tests/fixes/optimizations |
761 |
|
2249.5.12
by John Arbash Meinel
Change the APIs for VersionedFile, Store, and some of Repository into utf-8 |
762 |
self.assertTrue(index.has_version("a")) |
763 |
self.assertFalse(index.has_version("b")) |
|
2158.3.1
by Dmitry Vasiliev
KnitIndex tests/fixes/optimizations |
764 |
|
765 |
def test_get_position(self): |
|
766 |
transport = MockTransport([ |
|
767 |
_KnitIndex.HEADER, |
|
768 |
"a option 0 1 :", |
|
769 |
"b option 1 2 :"
|
|
770 |
])
|
|
2484.1.1
by John Arbash Meinel
Add an initial function to read knit indexes in pyrex. |
771 |
index = self.get_knit_index(transport, "filename", "r") |
2158.3.1
by Dmitry Vasiliev
KnitIndex tests/fixes/optimizations |
772 |
|
2670.2.2
by Robert Collins
* In ``bzrlib.knit`` the internal interface has been altered to use |
773 |
self.assertEqual((None, 0, 1), index.get_position("a")) |
774 |
self.assertEqual((None, 1, 2), index.get_position("b")) |
|
2158.3.1
by Dmitry Vasiliev
KnitIndex tests/fixes/optimizations |
775 |
|
776 |
def test_get_method(self): |
|
777 |
transport = MockTransport([ |
|
778 |
_KnitIndex.HEADER, |
|
779 |
"a fulltext,unknown 0 1 :", |
|
780 |
"b unknown,line-delta 1 2 :", |
|
781 |
"c bad 3 4 :"
|
|
782 |
])
|
|
2484.1.1
by John Arbash Meinel
Add an initial function to read knit indexes in pyrex. |
783 |
index = self.get_knit_index(transport, "filename", "r") |
2158.3.1
by Dmitry Vasiliev
KnitIndex tests/fixes/optimizations |
784 |
|
2249.5.12
by John Arbash Meinel
Change the APIs for VersionedFile, Store, and some of Repository into utf-8 |
785 |
self.assertEqual("fulltext", index.get_method("a")) |
786 |
self.assertEqual("line-delta", index.get_method("b")) |
|
787 |
self.assertRaises(errors.KnitIndexUnknownMethod, index.get_method, "c") |
|
2158.3.1
by Dmitry Vasiliev
KnitIndex tests/fixes/optimizations |
788 |
|
789 |
def test_get_options(self): |
|
790 |
transport = MockTransport([ |
|
791 |
_KnitIndex.HEADER, |
|
792 |
"a opt1 0 1 :", |
|
793 |
"b opt2,opt3 1 2 :"
|
|
794 |
])
|
|
2484.1.1
by John Arbash Meinel
Add an initial function to read knit indexes in pyrex. |
795 |
index = self.get_knit_index(transport, "filename", "r") |
2158.3.1
by Dmitry Vasiliev
KnitIndex tests/fixes/optimizations |
796 |
|
2249.5.12
by John Arbash Meinel
Change the APIs for VersionedFile, Store, and some of Repository into utf-8 |
797 |
self.assertEqual(["opt1"], index.get_options("a")) |
798 |
self.assertEqual(["opt2", "opt3"], index.get_options("b")) |
|
2158.3.1
by Dmitry Vasiliev
KnitIndex tests/fixes/optimizations |
799 |
|
800 |
def test_get_parents(self): |
|
801 |
transport = MockTransport([ |
|
802 |
_KnitIndex.HEADER, |
|
803 |
"a option 0 1 :", |
|
804 |
"b option 1 2 0 .c :", |
|
805 |
"c option 1 2 1 0 .e :"
|
|
806 |
])
|
|
2484.1.1
by John Arbash Meinel
Add an initial function to read knit indexes in pyrex. |
807 |
index = self.get_knit_index(transport, "filename", "r") |
2158.3.1
by Dmitry Vasiliev
KnitIndex tests/fixes/optimizations |
808 |
|
2249.5.12
by John Arbash Meinel
Change the APIs for VersionedFile, Store, and some of Repository into utf-8 |
809 |
self.assertEqual([], index.get_parents("a")) |
810 |
self.assertEqual(["a", "c"], index.get_parents("b")) |
|
811 |
self.assertEqual(["b", "a"], index.get_parents("c")) |
|
2158.3.1
by Dmitry Vasiliev
KnitIndex tests/fixes/optimizations |
812 |
|
813 |
def test_get_parents_with_ghosts(self): |
|
814 |
transport = MockTransport([ |
|
815 |
_KnitIndex.HEADER, |
|
816 |
"a option 0 1 :", |
|
817 |
"b option 1 2 0 .c :", |
|
818 |
"c option 1 2 1 0 .e :"
|
|
819 |
])
|
|
2484.1.1
by John Arbash Meinel
Add an initial function to read knit indexes in pyrex. |
820 |
index = self.get_knit_index(transport, "filename", "r") |
2158.3.1
by Dmitry Vasiliev
KnitIndex tests/fixes/optimizations |
821 |
|
2249.5.12
by John Arbash Meinel
Change the APIs for VersionedFile, Store, and some of Repository into utf-8 |
822 |
self.assertEqual([], index.get_parents_with_ghosts("a")) |
823 |
self.assertEqual(["a", "c"], index.get_parents_with_ghosts("b")) |
|
824 |
self.assertEqual(["b", "a", "e"], |
|
825 |
index.get_parents_with_ghosts("c")) |
|
2158.3.1
by Dmitry Vasiliev
KnitIndex tests/fixes/optimizations |
826 |
|
827 |
def test_check_versions_present(self): |
|
828 |
transport = MockTransport([ |
|
829 |
_KnitIndex.HEADER, |
|
830 |
"a option 0 1 :", |
|
831 |
"b option 0 1 :"
|
|
832 |
])
|
|
2484.1.1
by John Arbash Meinel
Add an initial function to read knit indexes in pyrex. |
833 |
index = self.get_knit_index(transport, "filename", "r") |
2158.3.1
by Dmitry Vasiliev
KnitIndex tests/fixes/optimizations |
834 |
|
835 |
check = index.check_versions_present |
|
836 |
||
837 |
check([]) |
|
2249.5.12
by John Arbash Meinel
Change the APIs for VersionedFile, Store, and some of Repository into utf-8 |
838 |
check(["a"]) |
839 |
check(["b"]) |
|
840 |
check(["a", "b"]) |
|
841 |
self.assertRaises(RevisionNotPresent, check, ["c"]) |
|
842 |
self.assertRaises(RevisionNotPresent, check, ["a", "b", "c"]) |
|
2158.3.1
by Dmitry Vasiliev
KnitIndex tests/fixes/optimizations |
843 |
|
2484.1.13
by John Arbash Meinel
Add a test that KnitCorrupt is raised when parent strings are invalid. |
844 |
def test_impossible_parent(self): |
845 |
"""Test we get KnitCorrupt if the parent couldn't possibly exist."""
|
|
846 |
transport = MockTransport([ |
|
847 |
_KnitIndex.HEADER, |
|
848 |
"a option 0 1 :", |
|
849 |
"b option 0 1 4 :" # We don't have a 4th record |
|
850 |
])
|
|
2484.1.17
by John Arbash Meinel
Workaround for Pyrex <0.9.5 and python >=2.5 incompatibilities. |
851 |
try: |
852 |
self.assertRaises(errors.KnitCorrupt, |
|
853 |
self.get_knit_index, transport, 'filename', 'r') |
|
854 |
except TypeError, e: |
|
855 |
if (str(e) == ('exceptions must be strings, classes, or instances,' |
|
856 |
' not exceptions.IndexError') |
|
857 |
and sys.version_info[0:2] >= (2,5)): |
|
858 |
self.knownFailure('Pyrex <0.9.5 fails with TypeError when' |
|
859 |
' raising new style exceptions with python'
|
|
860 |
' >=2.5') |
|
2484.1.19
by John Arbash Meinel
Don't suppress the TypeError if it doesn't match our requirements. |
861 |
else: |
862 |
raise
|
|
2484.1.13
by John Arbash Meinel
Add a test that KnitCorrupt is raised when parent strings are invalid. |
863 |
|
864 |
def test_corrupted_parent(self): |
|
865 |
transport = MockTransport([ |
|
866 |
_KnitIndex.HEADER, |
|
867 |
"a option 0 1 :", |
|
868 |
"b option 0 1 :", |
|
869 |
"c option 0 1 1v :", # Can't have a parent of '1v' |
|
870 |
])
|
|
2484.1.17
by John Arbash Meinel
Workaround for Pyrex <0.9.5 and python >=2.5 incompatibilities. |
871 |
try: |
872 |
self.assertRaises(errors.KnitCorrupt, |
|
873 |
self.get_knit_index, transport, 'filename', 'r') |
|
874 |
except TypeError, e: |
|
875 |
if (str(e) == ('exceptions must be strings, classes, or instances,' |
|
876 |
' not exceptions.ValueError') |
|
877 |
and sys.version_info[0:2] >= (2,5)): |
|
878 |
self.knownFailure('Pyrex <0.9.5 fails with TypeError when' |
|
879 |
' raising new style exceptions with python'
|
|
880 |
' >=2.5') |
|
2484.1.19
by John Arbash Meinel
Don't suppress the TypeError if it doesn't match our requirements. |
881 |
else: |
882 |
raise
|
|
2484.1.13
by John Arbash Meinel
Add a test that KnitCorrupt is raised when parent strings are invalid. |
883 |
|
884 |
def test_corrupted_parent_in_list(self): |
|
885 |
transport = MockTransport([ |
|
886 |
_KnitIndex.HEADER, |
|
887 |
"a option 0 1 :", |
|
888 |
"b option 0 1 :", |
|
2484.1.17
by John Arbash Meinel
Workaround for Pyrex <0.9.5 and python >=2.5 incompatibilities. |
889 |
"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. |
890 |
])
|
2484.1.17
by John Arbash Meinel
Workaround for Pyrex <0.9.5 and python >=2.5 incompatibilities. |
891 |
try: |
892 |
self.assertRaises(errors.KnitCorrupt, |
|
893 |
self.get_knit_index, transport, 'filename', 'r') |
|
894 |
except TypeError, e: |
|
895 |
if (str(e) == ('exceptions must be strings, classes, or instances,' |
|
896 |
' not exceptions.ValueError') |
|
897 |
and sys.version_info[0:2] >= (2,5)): |
|
898 |
self.knownFailure('Pyrex <0.9.5 fails with TypeError when' |
|
899 |
' raising new style exceptions with python'
|
|
900 |
' >=2.5') |
|
2484.1.19
by John Arbash Meinel
Don't suppress the TypeError if it doesn't match our requirements. |
901 |
else: |
902 |
raise
|
|
2484.1.13
by John Arbash Meinel
Add a test that KnitCorrupt is raised when parent strings are invalid. |
903 |
|
2484.1.18
by John Arbash Meinel
Test that we properly verify the size and position strings. |
904 |
def test_invalid_position(self): |
905 |
transport = MockTransport([ |
|
906 |
_KnitIndex.HEADER, |
|
907 |
"a option 1v 1 :", |
|
908 |
])
|
|
909 |
try: |
|
910 |
self.assertRaises(errors.KnitCorrupt, |
|
911 |
self.get_knit_index, transport, 'filename', 'r') |
|
912 |
except TypeError, e: |
|
913 |
if (str(e) == ('exceptions must be strings, classes, or instances,' |
|
914 |
' not exceptions.ValueError') |
|
915 |
and sys.version_info[0:2] >= (2,5)): |
|
916 |
self.knownFailure('Pyrex <0.9.5 fails with TypeError when' |
|
917 |
' raising new style exceptions with python'
|
|
918 |
' >=2.5') |
|
2484.1.19
by John Arbash Meinel
Don't suppress the TypeError if it doesn't match our requirements. |
919 |
else: |
920 |
raise
|
|
2484.1.18
by John Arbash Meinel
Test that we properly verify the size and position strings. |
921 |
|
922 |
def test_invalid_size(self): |
|
923 |
transport = MockTransport([ |
|
924 |
_KnitIndex.HEADER, |
|
925 |
"a option 1 1v :", |
|
926 |
])
|
|
927 |
try: |
|
928 |
self.assertRaises(errors.KnitCorrupt, |
|
929 |
self.get_knit_index, transport, 'filename', 'r') |
|
930 |
except TypeError, e: |
|
931 |
if (str(e) == ('exceptions must be strings, classes, or instances,' |
|
932 |
' not exceptions.ValueError') |
|
933 |
and sys.version_info[0:2] >= (2,5)): |
|
934 |
self.knownFailure('Pyrex <0.9.5 fails with TypeError when' |
|
935 |
' raising new style exceptions with python'
|
|
936 |
' >=2.5') |
|
2484.1.19
by John Arbash Meinel
Don't suppress the TypeError if it doesn't match our requirements. |
937 |
else: |
938 |
raise
|
|
2484.1.18
by John Arbash Meinel
Test that we properly verify the size and position strings. |
939 |
|
2484.1.24
by John Arbash Meinel
Add direct tests of how we handle incomplete/'broken' lines |
940 |
def test_short_line(self): |
941 |
transport = MockTransport([ |
|
942 |
_KnitIndex.HEADER, |
|
943 |
"a option 0 10 :", |
|
944 |
"b option 10 10 0", # This line isn't terminated, ignored |
|
945 |
])
|
|
946 |
index = self.get_knit_index(transport, "filename", "r") |
|
947 |
self.assertEqual(['a'], index.get_versions()) |
|
948 |
||
949 |
def test_skip_incomplete_record(self): |
|
950 |
# A line with bogus data should just be skipped
|
|
951 |
transport = MockTransport([ |
|
952 |
_KnitIndex.HEADER, |
|
953 |
"a option 0 10 :", |
|
954 |
"b option 10 10 0", # This line isn't terminated, ignored |
|
955 |
"c option 20 10 0 :", # Properly terminated, and starts with '\n' |
|
956 |
])
|
|
957 |
index = self.get_knit_index(transport, "filename", "r") |
|
958 |
self.assertEqual(['a', 'c'], index.get_versions()) |
|
959 |
||
960 |
def test_trailing_characters(self): |
|
961 |
# A line with bogus data should just be skipped
|
|
962 |
transport = MockTransport([ |
|
963 |
_KnitIndex.HEADER, |
|
964 |
"a option 0 10 :", |
|
965 |
"b option 10 10 0 :a", # This line has extra trailing characters |
|
966 |
"c option 20 10 0 :", # Properly terminated, and starts with '\n' |
|
967 |
])
|
|
968 |
index = self.get_knit_index(transport, "filename", "r") |
|
969 |
self.assertEqual(['a', 'c'], index.get_versions()) |
|
970 |
||
2158.3.1
by Dmitry Vasiliev
KnitIndex tests/fixes/optimizations |
971 |
|
2484.1.1
by John Arbash Meinel
Add an initial function to read knit indexes in pyrex. |
972 |
class LowLevelKnitIndexTests_c(LowLevelKnitIndexTests): |
973 |
||
974 |
_test_needs_features = [CompiledKnitFeature] |
|
975 |
||
976 |
def get_knit_index(self, *args, **kwargs): |
|
977 |
orig = knit._load_data |
|
978 |
def reset(): |
|
979 |
knit._load_data = orig |
|
980 |
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 |
981 |
from bzrlib._knit_load_data_c import _load_data_c |
982 |
knit._load_data = _load_data_c |
|
2484.1.1
by John Arbash Meinel
Add an initial function to read knit indexes in pyrex. |
983 |
return _KnitIndex(*args, **kwargs) |
984 |
||
985 |
||
986 |
||
1684.3.3
by Robert Collins
Add a special cased weaves to knit converter. |
987 |
class KnitTests(TestCaseWithTransport): |
988 |
"""Class containing knit test helper routines."""
|
|
1563.2.16
by Robert Collins
Change WeaveStore into VersionedFileStore and make its versoined file class parameterisable. |
989 |
|
2670.3.1
by Andrew Bennetts
Add get_data_stream/insert_data_stream to KnitVersionedFile. |
990 |
def make_test_knit(self, annotate=False, delay_create=False, index=None, |
991 |
name='test'): |
|
1563.2.16
by Robert Collins
Change WeaveStore into VersionedFileStore and make its versoined file class parameterisable. |
992 |
if not annotate: |
993 |
factory = KnitPlainFactory() |
|
994 |
else: |
|
995 |
factory = None |
|
2670.3.1
by Andrew Bennetts
Add get_data_stream/insert_data_stream to KnitVersionedFile. |
996 |
return KnitVersionedFile(name, get_transport('.'), access_mode='w', |
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 |
997 |
factory=factory, create=True, |
2625.8.1
by Robert Collins
LIBRARY API BREAKS: |
998 |
delay_create=delay_create, index=index) |
1563.2.4
by Robert Collins
First cut at including the knit implementation of versioned_file. |
999 |
|
2670.3.5
by Andrew Bennetts
Remove get_stream_as_bytes from KnitVersionedFile's API, make it a function in knitrepo.py instead. |
1000 |
def assertRecordContentEqual(self, knit, version_id, candidate_content): |
1001 |
"""Assert that some raw record content matches the raw record content
|
|
1002 |
for a particular version_id in the given knit.
|
|
1003 |
"""
|
|
1004 |
index_memo = knit._index.get_position(version_id) |
|
1005 |
record = (version_id, index_memo) |
|
1006 |
[(_, expected_content)] = list(knit._data.read_records_iter_raw([record])) |
|
1007 |
self.assertEqual(expected_content, candidate_content) |
|
1008 |
||
1684.3.3
by Robert Collins
Add a special cased weaves to knit converter. |
1009 |
|
1010 |
class BasicKnitTests(KnitTests): |
|
1011 |
||
1012 |
def add_stock_one_and_one_a(self, k): |
|
1013 |
k.add_lines('text-1', [], split_lines(TEXT_1)) |
|
1014 |
k.add_lines('text-1a', ['text-1'], split_lines(TEXT_1A)) |
|
1015 |
||
1016 |
def test_knit_constructor(self): |
|
1017 |
"""Construct empty k"""
|
|
1018 |
self.make_test_knit() |
|
1019 |
||
2625.8.1
by Robert Collins
LIBRARY API BREAKS: |
1020 |
def test_make_explicit_index(self): |
1021 |
"""We can supply an index to use."""
|
|
1022 |
knit = KnitVersionedFile('test', get_transport('.'), |
|
1023 |
index='strangelove') |
|
1024 |
self.assertEqual(knit._index, 'strangelove') |
|
1025 |
||
1563.2.4
by Robert Collins
First cut at including the knit implementation of versioned_file. |
1026 |
def test_knit_add(self): |
1027 |
"""Store one text in knit and retrieve"""
|
|
1563.2.16
by Robert Collins
Change WeaveStore into VersionedFileStore and make its versoined file class parameterisable. |
1028 |
k = self.make_test_knit() |
1563.2.4
by Robert Collins
First cut at including the knit implementation of versioned_file. |
1029 |
k.add_lines('text-1', [], split_lines(TEXT_1)) |
1030 |
self.assertTrue(k.has_version('text-1')) |
|
1031 |
self.assertEqualDiff(''.join(k.get_lines('text-1')), TEXT_1) |
|
1032 |
||
1033 |
def test_knit_reload(self): |
|
1641.1.2
by Robert Collins
Change knit index files to be robust in the presence of partial writes. |
1034 |
# 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. |
1035 |
k = self.make_test_knit() |
1563.2.4
by Robert Collins
First cut at including the knit implementation of versioned_file. |
1036 |
k.add_lines('text-1', [], split_lines(TEXT_1)) |
1037 |
del k |
|
1685.1.39
by John Arbash Meinel
Updating test_knit to not instantiate a LocalTransport directly. |
1038 |
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. |
1039 |
self.assertTrue(k2.has_version('text-1')) |
1040 |
self.assertEqualDiff(''.join(k2.get_lines('text-1')), TEXT_1) |
|
1041 |
||
1042 |
def test_knit_several(self): |
|
1043 |
"""Store several texts in a knit"""
|
|
1563.2.16
by Robert Collins
Change WeaveStore into VersionedFileStore and make its versoined file class parameterisable. |
1044 |
k = self.make_test_knit() |
1563.2.4
by Robert Collins
First cut at including the knit implementation of versioned_file. |
1045 |
k.add_lines('text-1', [], split_lines(TEXT_1)) |
1046 |
k.add_lines('text-2', [], split_lines(TEXT_2)) |
|
1047 |
self.assertEqualDiff(''.join(k.get_lines('text-1')), TEXT_1) |
|
1048 |
self.assertEqualDiff(''.join(k.get_lines('text-2')), TEXT_2) |
|
1049 |
||
1050 |
def test_repeated_add(self): |
|
1051 |
"""Knit traps attempt to replace existing version"""
|
|
1563.2.16
by Robert Collins
Change WeaveStore into VersionedFileStore and make its versoined file class parameterisable. |
1052 |
k = self.make_test_knit() |
1563.2.4
by Robert Collins
First cut at including the knit implementation of versioned_file. |
1053 |
k.add_lines('text-1', [], split_lines(TEXT_1)) |
1054 |
self.assertRaises(RevisionAlreadyPresent, |
|
1055 |
k.add_lines, |
|
1056 |
'text-1', [], split_lines(TEXT_1)) |
|
1057 |
||
1058 |
def test_empty(self): |
|
1563.2.16
by Robert Collins
Change WeaveStore into VersionedFileStore and make its versoined file class parameterisable. |
1059 |
k = self.make_test_knit(True) |
1563.2.4
by Robert Collins
First cut at including the knit implementation of versioned_file. |
1060 |
k.add_lines('text-1', [], []) |
1061 |
self.assertEquals(k.get_lines('text-1'), []) |
|
1062 |
||
1063 |
def test_incomplete(self): |
|
1064 |
"""Test if texts without a ending line-end can be inserted and
|
|
1065 |
extracted."""
|
|
1685.1.39
by John Arbash Meinel
Updating test_knit to not instantiate a LocalTransport directly. |
1066 |
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. |
1067 |
k.add_lines('text-1', [], ['a\n', 'b' ]) |
1068 |
k.add_lines('text-2', ['text-1'], ['a\rb\n', 'b\n']) |
|
1666.1.6
by Robert Collins
Make knit the default format. |
1069 |
# reopening ensures maximum room for confusion
|
1685.1.39
by John Arbash Meinel
Updating test_knit to not instantiate a LocalTransport directly. |
1070 |
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. |
1071 |
self.assertEquals(k.get_lines('text-1'), ['a\n', 'b' ]) |
1072 |
self.assertEquals(k.get_lines('text-2'), ['a\rb\n', 'b\n']) |
|
1073 |
||
1074 |
def test_delta(self): |
|
1075 |
"""Expression of knit delta as lines"""
|
|
1563.2.16
by Robert Collins
Change WeaveStore into VersionedFileStore and make its versoined file class parameterisable. |
1076 |
k = self.make_test_knit() |
2520.4.41
by Aaron Bentley
Accelerate mpdiff generation |
1077 |
KnitContent
|
1563.2.4
by Robert Collins
First cut at including the knit implementation of versioned_file. |
1078 |
td = list(line_delta(TEXT_1.splitlines(True), |
1079 |
TEXT_1A.splitlines(True))) |
|
1080 |
self.assertEqualDiff(''.join(td), delta_1_1a) |
|
1081 |
out = apply_line_delta(TEXT_1.splitlines(True), td) |
|
1082 |
self.assertEqualDiff(''.join(out), TEXT_1A) |
|
1083 |
||
2520.4.47
by Aaron Bentley
Fix get_line_delta_blocks with eol |
1084 |
def assertDerivedBlocksEqual(self, source, target, noeol=False): |
2520.4.41
by Aaron Bentley
Accelerate mpdiff generation |
1085 |
"""Assert that the derived matching blocks match real output"""
|
1086 |
source_lines = source.splitlines(True) |
|
1087 |
target_lines = target.splitlines(True) |
|
2520.4.47
by Aaron Bentley
Fix get_line_delta_blocks with eol |
1088 |
def nl(line): |
1089 |
if noeol and not line.endswith('\n'): |
|
1090 |
return line + '\n' |
|
1091 |
else: |
|
1092 |
return line |
|
1093 |
source_content = KnitContent([(None, nl(l)) for l in source_lines]) |
|
1094 |
target_content = KnitContent([(None, nl(l)) for l in target_lines]) |
|
2520.4.41
by Aaron Bentley
Accelerate mpdiff generation |
1095 |
line_delta = source_content.line_delta(target_content) |
2520.4.47
by Aaron Bentley
Fix get_line_delta_blocks with eol |
1096 |
delta_blocks = list(KnitContent.get_line_delta_blocks(line_delta, |
1097 |
source_lines, target_lines)) |
|
2520.4.41
by Aaron Bentley
Accelerate mpdiff generation |
1098 |
matcher = KnitSequenceMatcher(None, source_lines, target_lines) |
2520.4.47
by Aaron Bentley
Fix get_line_delta_blocks with eol |
1099 |
matcher_blocks = list(list(matcher.get_matching_blocks())) |
1100 |
self.assertEqual(matcher_blocks, delta_blocks) |
|
2520.4.41
by Aaron Bentley
Accelerate mpdiff generation |
1101 |
|
1102 |
def test_get_line_delta_blocks(self): |
|
1103 |
self.assertDerivedBlocksEqual('a\nb\nc\n', 'q\nc\n') |
|
1104 |
self.assertDerivedBlocksEqual(TEXT_1, TEXT_1) |
|
1105 |
self.assertDerivedBlocksEqual(TEXT_1, TEXT_1A) |
|
1106 |
self.assertDerivedBlocksEqual(TEXT_1, TEXT_1B) |
|
1107 |
self.assertDerivedBlocksEqual(TEXT_1B, TEXT_1A) |
|
1108 |
self.assertDerivedBlocksEqual(TEXT_1A, TEXT_1B) |
|
1109 |
self.assertDerivedBlocksEqual(TEXT_1A, '') |
|
1110 |
self.assertDerivedBlocksEqual('', TEXT_1A) |
|
1111 |
self.assertDerivedBlocksEqual('', '') |
|
2520.4.47
by Aaron Bentley
Fix get_line_delta_blocks with eol |
1112 |
self.assertDerivedBlocksEqual('a\nb\nc', 'a\nb\nc\nd') |
1113 |
||
1114 |
def test_get_line_delta_blocks_noeol(self): |
|
2520.4.48
by Aaron Bentley
Support getting blocks from knit deltas with no final EOL |
1115 |
"""Handle historical knit deltas safely
|
1116 |
||
1117 |
Some existing knit deltas don't consider the last line to differ
|
|
1118 |
when the only difference whether it has a final newline.
|
|
1119 |
||
1120 |
New knit deltas appear to always consider the last line to differ
|
|
1121 |
in this case.
|
|
1122 |
"""
|
|
2520.4.47
by Aaron Bentley
Fix get_line_delta_blocks with eol |
1123 |
self.assertDerivedBlocksEqual('a\nb\nc', 'a\nb\nc\nd\n', noeol=True) |
1124 |
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 |
1125 |
self.assertDerivedBlocksEqual('a\nb\nc\n', 'a\nb\nc', noeol=True) |
1126 |
self.assertDerivedBlocksEqual('a\nb\nc', 'a\nb\nc\n', noeol=True) |
|
2520.4.41
by Aaron Bentley
Accelerate mpdiff generation |
1127 |
|
1563.2.4
by Robert Collins
First cut at including the knit implementation of versioned_file. |
1128 |
def test_add_with_parents(self): |
1129 |
"""Store in knit with parents"""
|
|
1563.2.16
by Robert Collins
Change WeaveStore into VersionedFileStore and make its versoined file class parameterisable. |
1130 |
k = self.make_test_knit() |
1563.2.4
by Robert Collins
First cut at including the knit implementation of versioned_file. |
1131 |
self.add_stock_one_and_one_a(k) |
1132 |
self.assertEquals(k.get_parents('text-1'), []) |
|
1133 |
self.assertEquals(k.get_parents('text-1a'), ['text-1']) |
|
1134 |
||
1135 |
def test_ancestry(self): |
|
1136 |
"""Store in knit with parents"""
|
|
1563.2.16
by Robert Collins
Change WeaveStore into VersionedFileStore and make its versoined file class parameterisable. |
1137 |
k = self.make_test_knit() |
1563.2.4
by Robert Collins
First cut at including the knit implementation of versioned_file. |
1138 |
self.add_stock_one_and_one_a(k) |
1139 |
self.assertEquals(set(k.get_ancestry(['text-1a'])), set(['text-1a', 'text-1'])) |
|
1140 |
||
1141 |
def test_add_delta(self): |
|
1142 |
"""Store in knit with parents"""
|
|
1685.1.39
by John Arbash Meinel
Updating test_knit to not instantiate a LocalTransport directly. |
1143 |
k = KnitVersionedFile('test', get_transport('.'), factory=KnitPlainFactory(), |
1563.2.25
by Robert Collins
Merge in upstream. |
1144 |
delta=True, create=True) |
1563.2.4
by Robert Collins
First cut at including the knit implementation of versioned_file. |
1145 |
self.add_stock_one_and_one_a(k) |
1596.2.7
by Robert Collins
Remove the requirement for reannotation in knit joins. |
1146 |
k.clear_cache() |
1563.2.4
by Robert Collins
First cut at including the knit implementation of versioned_file. |
1147 |
self.assertEqualDiff(''.join(k.get_lines('text-1a')), TEXT_1A) |
1148 |
||
2625.8.1
by Robert Collins
LIBRARY API BREAKS: |
1149 |
def test_add_delta_knit_graph_index(self): |
1150 |
"""Does adding work with a KnitGraphIndex."""
|
|
1151 |
index = InMemoryGraphIndex(2) |
|
1152 |
knit_index = KnitGraphIndex(index, add_callback=index.add_nodes, |
|
1153 |
deltas=True) |
|
1154 |
k = KnitVersionedFile('test', get_transport('.'), |
|
1155 |
delta=True, create=True, index=knit_index) |
|
1156 |
self.add_stock_one_and_one_a(k) |
|
1157 |
k.clear_cache() |
|
1158 |
self.assertEqualDiff(''.join(k.get_lines('text-1a')), TEXT_1A) |
|
1159 |
# check the index had the right data added.
|
|
1160 |
self.assertEqual(set([ |
|
2624.2.14
by Robert Collins
Add source index to the index iteration API to allow mapping back to the origin of retrieved data. |
1161 |
(index, ('text-1', ), ' 0 127', ((), ())), |
1162 |
(index, ('text-1a', ), ' 127 140', ((('text-1', ),), (('text-1', ),))), |
|
2625.8.1
by Robert Collins
LIBRARY API BREAKS: |
1163 |
]), set(index.iter_all_entries())) |
1164 |
# we should not have a .kndx file
|
|
1165 |
self.assertFalse(get_transport('.').has('test.kndx')) |
|
1166 |
||
1563.2.4
by Robert Collins
First cut at including the knit implementation of versioned_file. |
1167 |
def test_annotate(self): |
1168 |
"""Annotations"""
|
|
1685.1.39
by John Arbash Meinel
Updating test_knit to not instantiate a LocalTransport directly. |
1169 |
k = KnitVersionedFile('knit', get_transport('.'), factory=KnitAnnotateFactory(), |
1563.2.25
by Robert Collins
Merge in upstream. |
1170 |
delta=True, create=True) |
1563.2.4
by Robert Collins
First cut at including the knit implementation of versioned_file. |
1171 |
self.insert_and_test_small_annotate(k) |
1172 |
||
1173 |
def insert_and_test_small_annotate(self, k): |
|
1174 |
"""test annotation with k works correctly."""
|
|
1175 |
k.add_lines('text-1', [], ['a\n', 'b\n']) |
|
1176 |
k.add_lines('text-2', ['text-1'], ['a\n', 'c\n']) |
|
1177 |
||
1178 |
origins = k.annotate('text-2') |
|
1179 |
self.assertEquals(origins[0], ('text-1', 'a\n')) |
|
1180 |
self.assertEquals(origins[1], ('text-2', 'c\n')) |
|
1181 |
||
1182 |
def test_annotate_fulltext(self): |
|
1183 |
"""Annotations"""
|
|
1685.1.39
by John Arbash Meinel
Updating test_knit to not instantiate a LocalTransport directly. |
1184 |
k = KnitVersionedFile('knit', get_transport('.'), factory=KnitAnnotateFactory(), |
1563.2.25
by Robert Collins
Merge in upstream. |
1185 |
delta=False, create=True) |
1563.2.4
by Robert Collins
First cut at including the knit implementation of versioned_file. |
1186 |
self.insert_and_test_small_annotate(k) |
1187 |
||
1188 |
def test_annotate_merge_1(self): |
|
1563.2.16
by Robert Collins
Change WeaveStore into VersionedFileStore and make its versoined file class parameterisable. |
1189 |
k = self.make_test_knit(True) |
1563.2.4
by Robert Collins
First cut at including the knit implementation of versioned_file. |
1190 |
k.add_lines('text-a1', [], ['a\n', 'b\n']) |
1191 |
k.add_lines('text-a2', [], ['d\n', 'c\n']) |
|
1192 |
k.add_lines('text-am', ['text-a1', 'text-a2'], ['d\n', 'b\n']) |
|
1193 |
origins = k.annotate('text-am') |
|
1194 |
self.assertEquals(origins[0], ('text-a2', 'd\n')) |
|
1195 |
self.assertEquals(origins[1], ('text-a1', 'b\n')) |
|
1196 |
||
1197 |
def test_annotate_merge_2(self): |
|
1563.2.16
by Robert Collins
Change WeaveStore into VersionedFileStore and make its versoined file class parameterisable. |
1198 |
k = self.make_test_knit(True) |
1563.2.4
by Robert Collins
First cut at including the knit implementation of versioned_file. |
1199 |
k.add_lines('text-a1', [], ['a\n', 'b\n', 'c\n']) |
1200 |
k.add_lines('text-a2', [], ['x\n', 'y\n', 'z\n']) |
|
1201 |
k.add_lines('text-am', ['text-a1', 'text-a2'], ['a\n', 'y\n', 'c\n']) |
|
1202 |
origins = k.annotate('text-am') |
|
1203 |
self.assertEquals(origins[0], ('text-a1', 'a\n')) |
|
1204 |
self.assertEquals(origins[1], ('text-a2', 'y\n')) |
|
1205 |
self.assertEquals(origins[2], ('text-a1', 'c\n')) |
|
1206 |
||
1207 |
def test_annotate_merge_9(self): |
|
1563.2.16
by Robert Collins
Change WeaveStore into VersionedFileStore and make its versoined file class parameterisable. |
1208 |
k = self.make_test_knit(True) |
1563.2.4
by Robert Collins
First cut at including the knit implementation of versioned_file. |
1209 |
k.add_lines('text-a1', [], ['a\n', 'b\n', 'c\n']) |
1210 |
k.add_lines('text-a2', [], ['x\n', 'y\n', 'z\n']) |
|
1211 |
k.add_lines('text-am', ['text-a1', 'text-a2'], ['k\n', 'y\n', 'c\n']) |
|
1212 |
origins = k.annotate('text-am') |
|
1213 |
self.assertEquals(origins[0], ('text-am', 'k\n')) |
|
1214 |
self.assertEquals(origins[1], ('text-a2', 'y\n')) |
|
1215 |
self.assertEquals(origins[2], ('text-a1', 'c\n')) |
|
1216 |
||
1217 |
def test_annotate_merge_3(self): |
|
1563.2.16
by Robert Collins
Change WeaveStore into VersionedFileStore and make its versoined file class parameterisable. |
1218 |
k = self.make_test_knit(True) |
1563.2.4
by Robert Collins
First cut at including the knit implementation of versioned_file. |
1219 |
k.add_lines('text-a1', [], ['a\n', 'b\n', 'c\n']) |
1220 |
k.add_lines('text-a2', [] ,['x\n', 'y\n', 'z\n']) |
|
1221 |
k.add_lines('text-am', ['text-a1', 'text-a2'], ['k\n', 'y\n', 'z\n']) |
|
1222 |
origins = k.annotate('text-am') |
|
1223 |
self.assertEquals(origins[0], ('text-am', 'k\n')) |
|
1224 |
self.assertEquals(origins[1], ('text-a2', 'y\n')) |
|
1225 |
self.assertEquals(origins[2], ('text-a2', 'z\n')) |
|
1226 |
||
1227 |
def test_annotate_merge_4(self): |
|
1563.2.16
by Robert Collins
Change WeaveStore into VersionedFileStore and make its versoined file class parameterisable. |
1228 |
k = self.make_test_knit(True) |
1563.2.4
by Robert Collins
First cut at including the knit implementation of versioned_file. |
1229 |
k.add_lines('text-a1', [], ['a\n', 'b\n', 'c\n']) |
1230 |
k.add_lines('text-a2', [], ['x\n', 'y\n', 'z\n']) |
|
1231 |
k.add_lines('text-a3', ['text-a1'], ['a\n', 'b\n', 'p\n']) |
|
1232 |
k.add_lines('text-am', ['text-a2', 'text-a3'], ['a\n', 'b\n', 'z\n']) |
|
1233 |
origins = k.annotate('text-am') |
|
1234 |
self.assertEquals(origins[0], ('text-a1', 'a\n')) |
|
1235 |
self.assertEquals(origins[1], ('text-a1', 'b\n')) |
|
1236 |
self.assertEquals(origins[2], ('text-a2', 'z\n')) |
|
1237 |
||
1238 |
def test_annotate_merge_5(self): |
|
1563.2.16
by Robert Collins
Change WeaveStore into VersionedFileStore and make its versoined file class parameterisable. |
1239 |
k = self.make_test_knit(True) |
1563.2.4
by Robert Collins
First cut at including the knit implementation of versioned_file. |
1240 |
k.add_lines('text-a1', [], ['a\n', 'b\n', 'c\n']) |
1241 |
k.add_lines('text-a2', [], ['d\n', 'e\n', 'f\n']) |
|
1242 |
k.add_lines('text-a3', [], ['x\n', 'y\n', 'z\n']) |
|
1243 |
k.add_lines('text-am', |
|
1244 |
['text-a1', 'text-a2', 'text-a3'], |
|
1245 |
['a\n', 'e\n', 'z\n']) |
|
1246 |
origins = k.annotate('text-am') |
|
1247 |
self.assertEquals(origins[0], ('text-a1', 'a\n')) |
|
1248 |
self.assertEquals(origins[1], ('text-a2', 'e\n')) |
|
1249 |
self.assertEquals(origins[2], ('text-a3', 'z\n')) |
|
1250 |
||
1251 |
def test_annotate_file_cherry_pick(self): |
|
1563.2.16
by Robert Collins
Change WeaveStore into VersionedFileStore and make its versoined file class parameterisable. |
1252 |
k = self.make_test_knit(True) |
1563.2.4
by Robert Collins
First cut at including the knit implementation of versioned_file. |
1253 |
k.add_lines('text-1', [], ['a\n', 'b\n', 'c\n']) |
1254 |
k.add_lines('text-2', ['text-1'], ['d\n', 'e\n', 'f\n']) |
|
1255 |
k.add_lines('text-3', ['text-2', 'text-1'], ['a\n', 'b\n', 'c\n']) |
|
1256 |
origins = k.annotate('text-3') |
|
1257 |
self.assertEquals(origins[0], ('text-1', 'a\n')) |
|
1258 |
self.assertEquals(origins[1], ('text-1', 'b\n')) |
|
1259 |
self.assertEquals(origins[2], ('text-1', 'c\n')) |
|
1260 |
||
1261 |
def test_knit_join(self): |
|
1262 |
"""Store in knit with parents"""
|
|
1685.1.39
by John Arbash Meinel
Updating test_knit to not instantiate a LocalTransport directly. |
1263 |
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. |
1264 |
k1.add_lines('text-a', [], split_lines(TEXT_1)) |
1265 |
k1.add_lines('text-b', ['text-a'], split_lines(TEXT_1)) |
|
1266 |
||
1267 |
k1.add_lines('text-c', [], split_lines(TEXT_1)) |
|
1268 |
k1.add_lines('text-d', ['text-c'], split_lines(TEXT_1)) |
|
1269 |
||
1270 |
k1.add_lines('text-m', ['text-b', 'text-d'], split_lines(TEXT_1)) |
|
1271 |
||
1685.1.39
by John Arbash Meinel
Updating test_knit to not instantiate a LocalTransport directly. |
1272 |
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. |
1273 |
count = k2.join(k1, version_ids=['text-m']) |
1274 |
self.assertEquals(count, 5) |
|
1275 |
self.assertTrue(k2.has_version('text-a')) |
|
1276 |
self.assertTrue(k2.has_version('text-c')) |
|
1277 |
||
1278 |
def test_reannotate(self): |
|
1685.1.39
by John Arbash Meinel
Updating test_knit to not instantiate a LocalTransport directly. |
1279 |
k1 = KnitVersionedFile('knit1', get_transport('.'), |
1563.2.25
by Robert Collins
Merge in upstream. |
1280 |
factory=KnitAnnotateFactory(), create=True) |
1563.2.4
by Robert Collins
First cut at including the knit implementation of versioned_file. |
1281 |
# 0
|
1282 |
k1.add_lines('text-a', [], ['a\n', 'b\n']) |
|
1283 |
# 1
|
|
1284 |
k1.add_lines('text-b', ['text-a'], ['a\n', 'c\n']) |
|
1285 |
||
1685.1.39
by John Arbash Meinel
Updating test_knit to not instantiate a LocalTransport directly. |
1286 |
k2 = KnitVersionedFile('test2', get_transport('.'), |
1563.2.25
by Robert Collins
Merge in upstream. |
1287 |
factory=KnitAnnotateFactory(), create=True) |
1563.2.4
by Robert Collins
First cut at including the knit implementation of versioned_file. |
1288 |
k2.join(k1, version_ids=['text-b']) |
1289 |
||
1290 |
# 2
|
|
1291 |
k1.add_lines('text-X', ['text-b'], ['a\n', 'b\n']) |
|
1292 |
# 2
|
|
1293 |
k2.add_lines('text-c', ['text-b'], ['z\n', 'c\n']) |
|
1294 |
# 3
|
|
1295 |
k2.add_lines('text-Y', ['text-b'], ['b\n', 'c\n']) |
|
1296 |
||
1297 |
# test-c will have index 3
|
|
1298 |
k1.join(k2, version_ids=['text-c']) |
|
1299 |
||
1300 |
lines = k1.get_lines('text-c') |
|
1301 |
self.assertEquals(lines, ['z\n', 'c\n']) |
|
1302 |
||
1303 |
origins = k1.annotate('text-c') |
|
1594.2.24
by Robert Collins
Make use of the transaction finalisation warning support to implement in-knit caching. |
1304 |
self.assertEquals(origins[0], ('text-c', 'z\n')) |
1305 |
self.assertEquals(origins[1], ('text-b', 'c\n')) |
|
1306 |
||
1756.3.4
by Aaron Bentley
Fix bug getting texts when line deltas were reused |
1307 |
def test_get_line_delta_texts(self): |
1308 |
"""Make sure we can call get_texts on text with reused line deltas"""
|
|
1309 |
k1 = KnitVersionedFile('test1', get_transport('.'), |
|
1310 |
factory=KnitPlainFactory(), create=True) |
|
1311 |
for t in range(3): |
|
1312 |
if t == 0: |
|
1313 |
parents = [] |
|
1314 |
else: |
|
1315 |
parents = ['%d' % (t-1)] |
|
1316 |
k1.add_lines('%d' % t, parents, ['hello\n'] * t) |
|
1317 |
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. |
1318 |
|
1319 |
def test_iter_lines_reads_in_order(self): |
|
1320 |
t = MemoryTransport() |
|
1321 |
instrumented_t = TransportLogger(t) |
|
1322 |
k1 = KnitVersionedFile('id', instrumented_t, create=True, delta=True) |
|
1323 |
self.assertEqual([('id.kndx',)], instrumented_t._calls) |
|
1324 |
# add texts with no required ordering
|
|
1325 |
k1.add_lines('base', [], ['text\n']) |
|
1326 |
k1.add_lines('base2', [], ['text2\n']) |
|
1327 |
k1.clear_cache() |
|
1328 |
instrumented_t._calls = [] |
|
1329 |
# request a last-first iteration
|
|
1330 |
results = list(k1.iter_lines_added_or_present_in_versions(['base2', 'base'])) |
|
1628.1.2
by Robert Collins
More knit micro-optimisations. |
1331 |
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. |
1332 |
self.assertEqual(['text\n', 'text2\n'], results) |
1563.2.4
by Robert Collins
First cut at including the knit implementation of versioned_file. |
1333 |
|
1563.2.13
by Robert Collins
InterVersionedFile implemented. |
1334 |
def test_create_empty_annotated(self): |
1563.2.16
by Robert Collins
Change WeaveStore into VersionedFileStore and make its versoined file class parameterisable. |
1335 |
k1 = self.make_test_knit(True) |
1563.2.13
by Robert Collins
InterVersionedFile implemented. |
1336 |
# 0
|
1337 |
k1.add_lines('text-a', [], ['a\n', 'b\n']) |
|
1338 |
k2 = k1.create_empty('t', MemoryTransport()) |
|
1339 |
self.assertTrue(isinstance(k2.factory, KnitAnnotateFactory)) |
|
1340 |
self.assertEqual(k1.delta, k2.delta) |
|
1341 |
# the generic test checks for empty content and file class
|
|
1342 |
||
1641.1.2
by Robert Collins
Change knit index files to be robust in the presence of partial writes. |
1343 |
def test_knit_format(self): |
1344 |
# this tests that a new knit index file has the expected content
|
|
1345 |
# and that is writes the data we expect as records are added.
|
|
1346 |
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 |
1347 |
# Now knit files are not created until we first add data to them
|
1666.1.6
by Robert Collins
Make knit the default format. |
1348 |
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. |
1349 |
knit.add_lines_with_ghosts('revid', ['a_ghost'], ['a\n']) |
1350 |
self.assertFileEqual( |
|
1666.1.6
by Robert Collins
Make knit the default format. |
1351 |
"# bzr knit index 8\n" |
1641.1.2
by Robert Collins
Change knit index files to be robust in the presence of partial writes. |
1352 |
"\n" |
1353 |
"revid fulltext 0 84 .a_ghost :", |
|
1354 |
'test.kndx') |
|
1355 |
knit.add_lines_with_ghosts('revid2', ['revid'], ['a\n']) |
|
1356 |
self.assertFileEqual( |
|
1666.1.6
by Robert Collins
Make knit the default format. |
1357 |
"# bzr knit index 8\n" |
1641.1.2
by Robert Collins
Change knit index files to be robust in the presence of partial writes. |
1358 |
"\nrevid fulltext 0 84 .a_ghost :" |
1359 |
"\nrevid2 line-delta 84 82 0 :", |
|
1360 |
'test.kndx') |
|
1361 |
# 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. |
1362 |
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. |
1363 |
self.assertEqual(['revid', 'revid2'], knit.versions()) |
1364 |
# 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 |
1365 |
indexfile = file('test.kndx', 'ab') |
1641.1.2
by Robert Collins
Change knit index files to be robust in the presence of partial writes. |
1366 |
indexfile.write('\nrevid3 line-delta 166 82 1 2 3 4 5 .phwoar:demo ') |
1367 |
indexfile.close() |
|
1368 |
# 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. |
1369 |
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. |
1370 |
self.assertEqual(['revid', 'revid2'], knit.versions()) |
1371 |
# and add a revision with the same id the failed write had
|
|
1372 |
knit.add_lines('revid3', ['revid2'], ['a\n']) |
|
1373 |
# and when reading it revid3 should now appear.
|
|
1685.1.39
by John Arbash Meinel
Updating test_knit to not instantiate a LocalTransport directly. |
1374 |
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. |
1375 |
self.assertEqual(['revid', 'revid2', 'revid3'], knit.versions()) |
1376 |
self.assertEqual(['revid2'], knit.get_parents('revid3')) |
|
1377 |
||
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 |
1378 |
def test_delay_create(self): |
1379 |
"""Test that passing delay_create=True creates files late"""
|
|
1380 |
knit = self.make_test_knit(annotate=True, delay_create=True) |
|
1381 |
self.failIfExists('test.knit') |
|
1382 |
self.failIfExists('test.kndx') |
|
1383 |
knit.add_lines_with_ghosts('revid', ['a_ghost'], ['a\n']) |
|
1384 |
self.failUnlessExists('test.knit') |
|
1385 |
self.assertFileEqual( |
|
1386 |
"# bzr knit index 8\n" |
|
1387 |
"\n" |
|
1388 |
"revid fulltext 0 84 .a_ghost :", |
|
1389 |
'test.kndx') |
|
1390 |
||
1946.2.2
by John Arbash Meinel
test delay_create does the right thing |
1391 |
def test_create_parent_dir(self): |
1392 |
"""create_parent_dir can create knits in nonexistant dirs"""
|
|
1393 |
# Has no effect if we don't set 'delay_create'
|
|
1394 |
trans = get_transport('.') |
|
1395 |
self.assertRaises(NoSuchFile, KnitVersionedFile, 'dir/test', |
|
1396 |
trans, access_mode='w', factory=None, |
|
1397 |
create=True, create_parent_dir=True) |
|
1398 |
# Nothing should have changed yet
|
|
1399 |
knit = KnitVersionedFile('dir/test', trans, access_mode='w', |
|
1400 |
factory=None, create=True, |
|
1401 |
create_parent_dir=True, |
|
1402 |
delay_create=True) |
|
1403 |
self.failIfExists('dir/test.knit') |
|
1404 |
self.failIfExists('dir/test.kndx') |
|
1405 |
self.failIfExists('dir') |
|
1406 |
knit.add_lines('revid', [], ['a\n']) |
|
1407 |
self.failUnlessExists('dir') |
|
1408 |
self.failUnlessExists('dir/test.knit') |
|
1409 |
self.assertFileEqual( |
|
1410 |
"# bzr knit index 8\n" |
|
1411 |
"\n" |
|
1412 |
"revid fulltext 0 84 :", |
|
1413 |
'dir/test.kndx') |
|
1414 |
||
1946.2.13
by John Arbash Meinel
Test that passing modes does the right thing for knits. |
1415 |
def test_create_mode_700(self): |
1416 |
trans = get_transport('.') |
|
1417 |
if not trans._can_roundtrip_unix_modebits(): |
|
1418 |
# Can't roundtrip, so no need to run this test
|
|
1419 |
return
|
|
1420 |
knit = KnitVersionedFile('dir/test', trans, access_mode='w', |
|
1421 |
factory=None, create=True, |
|
1422 |
create_parent_dir=True, |
|
1423 |
delay_create=True, |
|
1424 |
file_mode=0600, |
|
1425 |
dir_mode=0700) |
|
1426 |
knit.add_lines('revid', [], ['a\n']) |
|
1427 |
self.assertTransportMode(trans, 'dir', 0700) |
|
1428 |
self.assertTransportMode(trans, 'dir/test.knit', 0600) |
|
1429 |
self.assertTransportMode(trans, 'dir/test.kndx', 0600) |
|
1430 |
||
1431 |
def test_create_mode_770(self): |
|
1432 |
trans = get_transport('.') |
|
1433 |
if not trans._can_roundtrip_unix_modebits(): |
|
1434 |
# Can't roundtrip, so no need to run this test
|
|
1435 |
return
|
|
1436 |
knit = KnitVersionedFile('dir/test', trans, access_mode='w', |
|
1437 |
factory=None, create=True, |
|
1438 |
create_parent_dir=True, |
|
1439 |
delay_create=True, |
|
1440 |
file_mode=0660, |
|
1441 |
dir_mode=0770) |
|
1442 |
knit.add_lines('revid', [], ['a\n']) |
|
1443 |
self.assertTransportMode(trans, 'dir', 0770) |
|
1444 |
self.assertTransportMode(trans, 'dir/test.knit', 0660) |
|
1445 |
self.assertTransportMode(trans, 'dir/test.kndx', 0660) |
|
1446 |
||
1447 |
def test_create_mode_777(self): |
|
1448 |
trans = get_transport('.') |
|
1449 |
if not trans._can_roundtrip_unix_modebits(): |
|
1450 |
# Can't roundtrip, so no need to run this test
|
|
1451 |
return
|
|
1452 |
knit = KnitVersionedFile('dir/test', trans, access_mode='w', |
|
1453 |
factory=None, create=True, |
|
1454 |
create_parent_dir=True, |
|
1455 |
delay_create=True, |
|
1456 |
file_mode=0666, |
|
1457 |
dir_mode=0777) |
|
1458 |
knit.add_lines('revid', [], ['a\n']) |
|
1459 |
self.assertTransportMode(trans, 'dir', 0777) |
|
1460 |
self.assertTransportMode(trans, 'dir/test.knit', 0666) |
|
1461 |
self.assertTransportMode(trans, 'dir/test.kndx', 0666) |
|
1462 |
||
1664.2.1
by Aaron Bentley
Start work on plan_merge test |
1463 |
def test_plan_merge(self): |
1464 |
my_knit = self.make_test_knit(annotate=True) |
|
1465 |
my_knit.add_lines('text1', [], split_lines(TEXT_1)) |
|
1466 |
my_knit.add_lines('text1a', ['text1'], split_lines(TEXT_1A)) |
|
1467 |
my_knit.add_lines('text1b', ['text1'], split_lines(TEXT_1B)) |
|
1664.2.3
by Aaron Bentley
Add failing test case |
1468 |
plan = list(my_knit.plan_merge('text1a', 'text1b')) |
1664.2.6
by Aaron Bentley
Got plan-merge passing tests |
1469 |
for plan_line, expected_line in zip(plan, AB_MERGE): |
1470 |
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. |
1471 |
|
2670.3.1
by Andrew Bennetts
Add get_data_stream/insert_data_stream to KnitVersionedFile. |
1472 |
def test_get_stream_empty(self): |
1473 |
"""Get a data stream for an empty knit file."""
|
|
1474 |
k1 = self.make_test_knit() |
|
1475 |
format, data_list, reader_callable = k1.get_data_stream([]) |
|
1476 |
self.assertEqual('knit-plain', format) |
|
1477 |
self.assertEqual([], data_list) |
|
1478 |
content = reader_callable(None) |
|
1479 |
self.assertEqual('', content) |
|
1480 |
self.assertIsInstance(content, str) |
|
1481 |
||
1482 |
def test_get_stream_one_version(self): |
|
1483 |
"""Get a data stream for a single record out of a knit containing just
|
|
1484 |
one record.
|
|
1485 |
"""
|
|
1486 |
k1 = self.make_test_knit() |
|
1487 |
test_data = [ |
|
1488 |
('text-a', [], TEXT_1), |
|
1489 |
]
|
|
1490 |
expected_data_list = [ |
|
1491 |
# version, options, length, parents
|
|
1492 |
('text-a', ['fulltext'], 122, []), |
|
1493 |
]
|
|
1494 |
for version_id, parents, lines in test_data: |
|
1495 |
k1.add_lines(version_id, parents, split_lines(lines)) |
|
1496 |
||
1497 |
format, data_list, reader_callable = k1.get_data_stream(['text-a']) |
|
1498 |
self.assertEqual('knit-plain', format) |
|
1499 |
self.assertEqual(expected_data_list, data_list) |
|
1500 |
# There's only one record in the knit, so the content should be the
|
|
1501 |
# entire knit data file's contents.
|
|
2670.3.2
by Andrew Bennetts
Merge from bzr.dev. |
1502 |
self.assertEqual(k1.transport.get_bytes(k1._data._access._filename), |
2670.3.1
by Andrew Bennetts
Add get_data_stream/insert_data_stream to KnitVersionedFile. |
1503 |
reader_callable(None)) |
1504 |
||
1505 |
def test_get_stream_get_one_version_of_many(self): |
|
1506 |
"""Get a data stream for just one version out of a knit containing many
|
|
1507 |
versions.
|
|
1508 |
"""
|
|
1509 |
k1 = self.make_test_knit() |
|
1510 |
# Insert the same data as test_knit_join, as they seem to cover a range
|
|
1511 |
# of cases (no parents, one parent, multiple parents).
|
|
1512 |
test_data = [ |
|
1513 |
('text-a', [], TEXT_1), |
|
1514 |
('text-b', ['text-a'], TEXT_1), |
|
1515 |
('text-c', [], TEXT_1), |
|
1516 |
('text-d', ['text-c'], TEXT_1), |
|
1517 |
('text-m', ['text-b', 'text-d'], TEXT_1), |
|
1518 |
]
|
|
1519 |
expected_data_list = [ |
|
1520 |
# version, options, length, parents
|
|
1521 |
('text-m', ['line-delta'], 84, ['text-b', 'text-d']), |
|
1522 |
]
|
|
1523 |
for version_id, parents, lines in test_data: |
|
1524 |
k1.add_lines(version_id, parents, split_lines(lines)) |
|
1525 |
||
1526 |
format, data_list, reader_callable = k1.get_data_stream(['text-m']) |
|
1527 |
self.assertEqual('knit-plain', format) |
|
1528 |
self.assertEqual(expected_data_list, data_list) |
|
1529 |
self.assertRecordContentEqual(k1, 'text-m', reader_callable(None)) |
|
1530 |
||
1531 |
def test_get_stream_ghost_parent(self): |
|
1532 |
"""Get a data stream for a version with a ghost parent."""
|
|
1533 |
k1 = self.make_test_knit() |
|
1534 |
# Test data
|
|
1535 |
k1.add_lines('text-a', [], split_lines(TEXT_1)) |
|
1536 |
k1.add_lines_with_ghosts('text-b', ['text-a', 'text-ghost'], |
|
1537 |
split_lines(TEXT_1)) |
|
1538 |
# Expected data
|
|
1539 |
expected_data_list = [ |
|
1540 |
# version, options, length, parents
|
|
1541 |
('text-b', ['line-delta'], 84, ['text-a', 'text-ghost']), |
|
1542 |
]
|
|
1543 |
||
1544 |
format, data_list, reader_callable = k1.get_data_stream(['text-b']) |
|
1545 |
self.assertEqual('knit-plain', format) |
|
1546 |
self.assertEqual(expected_data_list, data_list) |
|
1547 |
self.assertRecordContentEqual(k1, 'text-b', reader_callable(None)) |
|
1548 |
||
1549 |
def test_get_stream_get_multiple_records(self): |
|
1550 |
"""Get a stream for multiple records of a knit."""
|
|
1551 |
k1 = self.make_test_knit() |
|
1552 |
# Insert the same data as test_knit_join, as they seem to cover a range
|
|
1553 |
# of cases (no parents, one parent, multiple parents).
|
|
1554 |
test_data = [ |
|
1555 |
('text-a', [], TEXT_1), |
|
1556 |
('text-b', ['text-a'], TEXT_1), |
|
1557 |
('text-c', [], TEXT_1), |
|
1558 |
('text-d', ['text-c'], TEXT_1), |
|
1559 |
('text-m', ['text-b', 'text-d'], TEXT_1), |
|
1560 |
]
|
|
1561 |
expected_data_list = [ |
|
1562 |
# version, options, length, parents
|
|
1563 |
('text-b', ['line-delta'], 84, ['text-a']), |
|
1564 |
('text-d', ['line-delta'], 84, ['text-c']), |
|
1565 |
]
|
|
1566 |
for version_id, parents, lines in test_data: |
|
1567 |
k1.add_lines(version_id, parents, split_lines(lines)) |
|
1568 |
||
1569 |
# Note that even though we request the revision IDs in a particular
|
|
1570 |
# order, the data stream may return them in any order it likes. In this
|
|
1571 |
# case, they'll be in the order they were inserted into the knit.
|
|
1572 |
format, data_list, reader_callable = k1.get_data_stream( |
|
1573 |
['text-d', 'text-b']) |
|
1574 |
self.assertEqual('knit-plain', format) |
|
1575 |
self.assertEqual(expected_data_list, data_list) |
|
1576 |
self.assertRecordContentEqual(k1, 'text-b', reader_callable(84)) |
|
1577 |
self.assertRecordContentEqual(k1, 'text-d', reader_callable(84)) |
|
1578 |
self.assertEqual('', reader_callable(None), |
|
1579 |
"There should be no more bytes left to read.") |
|
1580 |
||
1581 |
def test_get_stream_all(self): |
|
1582 |
"""Get a data stream for all the records in a knit.
|
|
1583 |
||
1584 |
This exercises fulltext records, line-delta records, records with
|
|
1585 |
various numbers of parents, and reading multiple records out of the
|
|
1586 |
callable. These cases ought to all be exercised individually by the
|
|
1587 |
other test_get_stream_* tests; this test is basically just paranoia.
|
|
1588 |
"""
|
|
1589 |
k1 = self.make_test_knit() |
|
1590 |
# Insert the same data as test_knit_join, as they seem to cover a range
|
|
1591 |
# of cases (no parents, one parent, multiple parents).
|
|
1592 |
test_data = [ |
|
1593 |
('text-a', [], TEXT_1), |
|
1594 |
('text-b', ['text-a'], TEXT_1), |
|
1595 |
('text-c', [], TEXT_1), |
|
1596 |
('text-d', ['text-c'], TEXT_1), |
|
1597 |
('text-m', ['text-b', 'text-d'], TEXT_1), |
|
1598 |
]
|
|
1599 |
expected_data_list = [ |
|
1600 |
# version, options, length, parents
|
|
1601 |
('text-a', ['fulltext'], 122, []), |
|
1602 |
('text-b', ['line-delta'], 84, ['text-a']), |
|
1603 |
('text-c', ['fulltext'], 121, []), |
|
1604 |
('text-d', ['line-delta'], 84, ['text-c']), |
|
1605 |
('text-m', ['line-delta'], 84, ['text-b', 'text-d']), |
|
1606 |
]
|
|
1607 |
for version_id, parents, lines in test_data: |
|
1608 |
k1.add_lines(version_id, parents, split_lines(lines)) |
|
1609 |
||
1610 |
format, data_list, reader_callable = k1.get_data_stream( |
|
1611 |
['text-a', 'text-b', 'text-c', 'text-d', 'text-m']) |
|
1612 |
self.assertEqual('knit-plain', format) |
|
1613 |
self.assertEqual(expected_data_list, data_list) |
|
1614 |
for version_id, options, length, parents in expected_data_list: |
|
1615 |
bytes = reader_callable(length) |
|
1616 |
self.assertRecordContentEqual(k1, version_id, bytes) |
|
1617 |
||
1618 |
def assertKnitFilesEqual(self, knit1, knit2): |
|
1619 |
"""Assert that the contents of the index and data files of two knits are
|
|
1620 |
equal.
|
|
1621 |
"""
|
|
1622 |
self.assertEqual( |
|
2670.3.2
by Andrew Bennetts
Merge from bzr.dev. |
1623 |
knit1.transport.get_bytes(knit1._data._access._filename), |
1624 |
knit2.transport.get_bytes(knit2._data._access._filename)) |
|
2670.3.1
by Andrew Bennetts
Add get_data_stream/insert_data_stream to KnitVersionedFile. |
1625 |
self.assertEqual( |
1626 |
knit1.transport.get_bytes(knit1._index._filename), |
|
1627 |
knit2.transport.get_bytes(knit2._index._filename)) |
|
1628 |
||
1629 |
def test_insert_data_stream_empty(self): |
|
1630 |
"""Inserting a data stream with no records should not put any data into
|
|
1631 |
the knit.
|
|
1632 |
"""
|
|
1633 |
k1 = self.make_test_knit() |
|
1634 |
k1.insert_data_stream( |
|
1635 |
(k1.get_format_signature(), [], lambda ignored: '')) |
|
2670.3.2
by Andrew Bennetts
Merge from bzr.dev. |
1636 |
self.assertEqual('', k1.transport.get_bytes(k1._data._access._filename), |
2670.3.1
by Andrew Bennetts
Add get_data_stream/insert_data_stream to KnitVersionedFile. |
1637 |
"The .knit should be completely empty.") |
1638 |
self.assertEqual(k1._index.HEADER, |
|
1639 |
k1.transport.get_bytes(k1._index._filename), |
|
1640 |
"The .kndx should have nothing apart from the header.") |
|
1641 |
||
1642 |
def test_insert_data_stream_one_record(self): |
|
1643 |
"""Inserting a data stream with one record from a knit with one record
|
|
1644 |
results in byte-identical files.
|
|
1645 |
"""
|
|
1646 |
source = self.make_test_knit(name='source') |
|
1647 |
source.add_lines('text-a', [], split_lines(TEXT_1)) |
|
1648 |
data_stream = source.get_data_stream(['text-a']) |
|
1649 |
||
1650 |
target = self.make_test_knit(name='target') |
|
1651 |
target.insert_data_stream(data_stream) |
|
1652 |
||
1653 |
self.assertKnitFilesEqual(source, target) |
|
1654 |
||
1655 |
def test_insert_data_stream_records_already_present(self): |
|
1656 |
"""Insert a data stream where some records are alreday present in the
|
|
1657 |
target, and some not. Only the new records are inserted.
|
|
1658 |
"""
|
|
1659 |
source = self.make_test_knit(name='source') |
|
1660 |
target = self.make_test_knit(name='target') |
|
1661 |
# Insert 'text-a' into both source and target
|
|
1662 |
source.add_lines('text-a', [], split_lines(TEXT_1)) |
|
1663 |
target.insert_data_stream(source.get_data_stream(['text-a'])) |
|
1664 |
# Insert 'text-b' into just the source.
|
|
1665 |
source.add_lines('text-b', ['text-a'], split_lines(TEXT_1)) |
|
1666 |
# Get a data stream of both text-a and text-b, and insert it.
|
|
1667 |
data_stream = source.get_data_stream(['text-a', 'text-b']) |
|
1668 |
target.insert_data_stream(data_stream) |
|
1669 |
# The source and target will now be identical. This means the text-a
|
|
1670 |
# record was not added a second time.
|
|
1671 |
self.assertKnitFilesEqual(source, target) |
|
1672 |
||
1673 |
def test_insert_data_stream_multiple_records(self): |
|
1674 |
"""Inserting a data stream of all records from a knit with multiple
|
|
1675 |
records results in byte-identical files.
|
|
1676 |
"""
|
|
1677 |
source = self.make_test_knit(name='source') |
|
1678 |
source.add_lines('text-a', [], split_lines(TEXT_1)) |
|
1679 |
source.add_lines('text-b', ['text-a'], split_lines(TEXT_1)) |
|
1680 |
source.add_lines('text-c', [], split_lines(TEXT_1)) |
|
1681 |
data_stream = source.get_data_stream(['text-a', 'text-b', 'text-c']) |
|
1682 |
||
1683 |
target = self.make_test_knit(name='target') |
|
1684 |
target.insert_data_stream(data_stream) |
|
1685 |
||
1686 |
self.assertKnitFilesEqual(source, target) |
|
1687 |
||
1688 |
def test_insert_data_stream_ghost_parent(self): |
|
1689 |
"""Insert a data stream with a record that has a ghost parent."""
|
|
1690 |
# Make a knit with a record, text-a, that has a ghost parent.
|
|
1691 |
source = self.make_test_knit(name='source') |
|
1692 |
source.add_lines_with_ghosts('text-a', ['text-ghost'], |
|
1693 |
split_lines(TEXT_1)) |
|
1694 |
data_stream = source.get_data_stream(['text-a']) |
|
1695 |
||
1696 |
target = self.make_test_knit(name='target') |
|
1697 |
target.insert_data_stream(data_stream) |
|
1698 |
||
1699 |
self.assertKnitFilesEqual(source, target) |
|
1700 |
||
1701 |
# The target knit object is in a consistent state, i.e. the record we
|
|
1702 |
# just added is immediately visible.
|
|
1703 |
self.assertTrue(target.has_version('text-a')) |
|
1704 |
self.assertTrue(target.has_ghost('text-ghost')) |
|
1705 |
self.assertEqual(split_lines(TEXT_1), target.get_lines('text-a')) |
|
1706 |
||
1707 |
def test_insert_data_stream_inconsistent_version_lines(self): |
|
1708 |
"""Inserting a data stream which has different content for a version_id
|
|
1709 |
than already exists in the knit will raise KnitCorrupt.
|
|
1710 |
"""
|
|
1711 |
source = self.make_test_knit(name='source') |
|
1712 |
target = self.make_test_knit(name='target') |
|
1713 |
# Insert a different 'text-a' into both source and target
|
|
1714 |
source.add_lines('text-a', [], split_lines(TEXT_1)) |
|
1715 |
target.add_lines('text-a', [], split_lines(TEXT_2)) |
|
1716 |
# Insert a data stream with conflicting content into the target
|
|
1717 |
data_stream = source.get_data_stream(['text-a']) |
|
1718 |
self.assertRaises( |
|
1719 |
errors.KnitCorrupt, target.insert_data_stream, data_stream) |
|
1720 |
||
1721 |
def test_insert_data_stream_inconsistent_version_parents(self): |
|
1722 |
"""Inserting a data stream which has different parents for a version_id
|
|
1723 |
than already exists in the knit will raise KnitCorrupt.
|
|
1724 |
"""
|
|
1725 |
source = self.make_test_knit(name='source') |
|
1726 |
target = self.make_test_knit(name='target') |
|
1727 |
# Insert a different 'text-a' into both source and target. They differ
|
|
1728 |
# only by the parents list, the content is the same.
|
|
1729 |
source.add_lines_with_ghosts('text-a', [], split_lines(TEXT_1)) |
|
1730 |
target.add_lines_with_ghosts('text-a', ['a-ghost'], split_lines(TEXT_1)) |
|
1731 |
# Insert a data stream with conflicting content into the target
|
|
1732 |
data_stream = source.get_data_stream(['text-a']) |
|
1733 |
self.assertRaises( |
|
1734 |
errors.KnitCorrupt, target.insert_data_stream, data_stream) |
|
1735 |
||
1736 |
def test_insert_data_stream_incompatible_format(self): |
|
1737 |
"""A data stream in a different format to the target knit cannot be
|
|
1738 |
inserted.
|
|
1739 |
||
1740 |
It will raise KnitDataStreamIncompatible.
|
|
1741 |
"""
|
|
1742 |
data_stream = ('fake-format-signature', [], lambda _: '') |
|
1743 |
target = self.make_test_knit(name='target') |
|
1744 |
self.assertRaises( |
|
1745 |
errors.KnitDataStreamIncompatible, |
|
1746 |
target.insert_data_stream, data_stream) |
|
1747 |
||
1748 |
# * test that a stream of "already present version, then new version"
|
|
1749 |
# inserts correctly.
|
|
1563.2.4
by Robert Collins
First cut at including the knit implementation of versioned_file. |
1750 |
|
1751 |
TEXT_1 = """\ |
|
1752 |
Banana cup cakes:
|
|
1753 |
||
1754 |
- bananas
|
|
1755 |
- eggs
|
|
1756 |
- broken tea cups
|
|
1757 |
"""
|
|
1758 |
||
1759 |
TEXT_1A = """\ |
|
1760 |
Banana cup cake recipe
|
|
1761 |
(serves 6)
|
|
1762 |
||
1763 |
- bananas
|
|
1764 |
- eggs
|
|
1765 |
- broken tea cups
|
|
1766 |
- self-raising flour
|
|
1767 |
"""
|
|
1768 |
||
1664.2.1
by Aaron Bentley
Start work on plan_merge test |
1769 |
TEXT_1B = """\ |
1770 |
Banana cup cake recipe
|
|
1771 |
||
1772 |
- bananas (do not use plantains!!!)
|
|
1773 |
- broken tea cups
|
|
1774 |
- flour
|
|
1775 |
"""
|
|
1776 |
||
1563.2.4
by Robert Collins
First cut at including the knit implementation of versioned_file. |
1777 |
delta_1_1a = """\ |
1778 |
0,1,2
|
|
1779 |
Banana cup cake recipe
|
|
1780 |
(serves 6)
|
|
1781 |
5,5,1
|
|
1782 |
- self-raising flour
|
|
1783 |
"""
|
|
1784 |
||
1785 |
TEXT_2 = """\ |
|
1786 |
Boeuf bourguignon
|
|
1787 |
||
1788 |
- beef
|
|
1789 |
- red wine
|
|
1790 |
- small onions
|
|
1791 |
- carrot
|
|
1792 |
- mushrooms
|
|
1793 |
"""
|
|
1794 |
||
1664.2.3
by Aaron Bentley
Add failing test case |
1795 |
AB_MERGE_TEXT="""unchanged|Banana cup cake recipe |
1796 |
new-a|(serves 6)
|
|
1797 |
unchanged|
|
|
1798 |
killed-b|- bananas
|
|
1799 |
killed-b|- eggs
|
|
1800 |
new-b|- bananas (do not use plantains!!!)
|
|
1801 |
unchanged|- broken tea cups
|
|
1802 |
new-a|- self-raising flour
|
|
1664.2.6
by Aaron Bentley
Got plan-merge passing tests |
1803 |
new-b|- flour
|
1804 |
"""
|
|
1664.2.3
by Aaron Bentley
Add failing test case |
1805 |
AB_MERGE=[tuple(l.split('|')) for l in AB_MERGE_TEXT.splitlines(True)] |
1806 |
||
1807 |
||
1563.2.4
by Robert Collins
First cut at including the knit implementation of versioned_file. |
1808 |
def line_delta(from_lines, to_lines): |
1809 |
"""Generate line-based delta from one text to another"""
|
|
1810 |
s = difflib.SequenceMatcher(None, from_lines, to_lines) |
|
1811 |
for op in s.get_opcodes(): |
|
1812 |
if op[0] == 'equal': |
|
1813 |
continue
|
|
1814 |
yield '%d,%d,%d\n' % (op[1], op[2], op[4]-op[3]) |
|
1815 |
for i in range(op[3], op[4]): |
|
1816 |
yield to_lines[i] |
|
1817 |
||
1818 |
||
1819 |
def apply_line_delta(basis_lines, delta_lines): |
|
1820 |
"""Apply a line-based perfect diff
|
|
1821 |
|
|
1822 |
basis_lines -- text to apply the patch to
|
|
1823 |
delta_lines -- diff instructions and content
|
|
1824 |
"""
|
|
1825 |
out = basis_lines[:] |
|
1826 |
i = 0 |
|
1827 |
offset = 0 |
|
1828 |
while i < len(delta_lines): |
|
1829 |
l = delta_lines[i] |
|
1830 |
a, b, c = map(long, l.split(',')) |
|
1831 |
i = i + 1 |
|
1832 |
out[offset+a:offset+b] = delta_lines[i:i+c] |
|
1833 |
i = i + c |
|
1834 |
offset = offset + (b - a) + c |
|
1835 |
return out |
|
1684.3.3
by Robert Collins
Add a special cased weaves to knit converter. |
1836 |
|
1837 |
||
1838 |
class TestWeaveToKnit(KnitTests): |
|
1839 |
||
1840 |
def test_weave_to_knit_matches(self): |
|
1841 |
# check that the WeaveToKnit is_compatible function
|
|
1842 |
# registers True for a Weave to a Knit.
|
|
1843 |
w = Weave() |
|
1844 |
k = self.make_test_knit() |
|
1845 |
self.failUnless(WeaveToKnit.is_compatible(w, k)) |
|
1846 |
self.failIf(WeaveToKnit.is_compatible(k, w)) |
|
1847 |
self.failIf(WeaveToKnit.is_compatible(w, w)) |
|
1848 |
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 |
1849 |
|
1850 |
||
1851 |
class TestKnitCaching(KnitTests): |
|
1852 |
||
1853 |
def create_knit(self, cache_add=False): |
|
1854 |
k = self.make_test_knit(True) |
|
1855 |
if cache_add: |
|
1856 |
k.enable_cache() |
|
1857 |
||
1858 |
k.add_lines('text-1', [], split_lines(TEXT_1)) |
|
1859 |
k.add_lines('text-2', [], split_lines(TEXT_2)) |
|
1860 |
return k |
|
1861 |
||
1862 |
def test_no_caching(self): |
|
1863 |
k = self.create_knit() |
|
1864 |
# Nothing should be cached without setting 'enable_cache'
|
|
1865 |
self.assertEqual({}, k._data._cache) |
|
1866 |
||
1867 |
def test_cache_add_and_clear(self): |
|
1868 |
k = self.create_knit(True) |
|
1869 |
||
1870 |
self.assertEqual(['text-1', 'text-2'], sorted(k._data._cache.keys())) |
|
1871 |
||
1872 |
k.clear_cache() |
|
1873 |
self.assertEqual({}, k._data._cache) |
|
1874 |
||
1875 |
def test_cache_data_read_raw(self): |
|
1876 |
k = self.create_knit() |
|
1877 |
||
1878 |
# Now cache and read
|
|
1879 |
k.enable_cache() |
|
1880 |
||
1881 |
def read_one_raw(version): |
|
1882 |
pos_map = k._get_components_positions([version]) |
|
2670.2.2
by Robert Collins
* In ``bzrlib.knit`` the internal interface has been altered to use |
1883 |
method, index_memo, next = pos_map[version] |
1884 |
lst = list(k._data.read_records_iter_raw([(version, index_memo)])) |
|
1863.1.1
by John Arbash Meinel
Allow Versioned files to do caching if explicitly asked, and implement for Knit |
1885 |
self.assertEqual(1, len(lst)) |
1886 |
return lst[0] |
|
1887 |
||
1888 |
val = read_one_raw('text-1') |
|
1863.1.8
by John Arbash Meinel
Removing disk-backed-cache |
1889 |
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 |
1890 |
|
1891 |
k.clear_cache() |
|
1892 |
# After clear, new reads are not cached
|
|
1893 |
self.assertEqual({}, k._data._cache) |
|
1894 |
||
1895 |
val2 = read_one_raw('text-1') |
|
1896 |
self.assertEqual(val, val2) |
|
1897 |
self.assertEqual({}, k._data._cache) |
|
1898 |
||
1899 |
def test_cache_data_read(self): |
|
1900 |
k = self.create_knit() |
|
1901 |
||
1902 |
def read_one(version): |
|
1903 |
pos_map = k._get_components_positions([version]) |
|
2670.2.2
by Robert Collins
* In ``bzrlib.knit`` the internal interface has been altered to use |
1904 |
method, index_memo, next = pos_map[version] |
1905 |
lst = list(k._data.read_records_iter([(version, index_memo)])) |
|
1863.1.1
by John Arbash Meinel
Allow Versioned files to do caching if explicitly asked, and implement for Knit |
1906 |
self.assertEqual(1, len(lst)) |
1907 |
return lst[0] |
|
1908 |
||
1909 |
# Now cache and read
|
|
1910 |
k.enable_cache() |
|
1911 |
||
1912 |
val = read_one('text-2') |
|
1913 |
self.assertEqual(['text-2'], k._data._cache.keys()) |
|
1914 |
self.assertEqual('text-2', val[0]) |
|
1915 |
content, digest = k._data._parse_record('text-2', |
|
1916 |
k._data._cache['text-2']) |
|
1917 |
self.assertEqual(content, val[1]) |
|
1918 |
self.assertEqual(digest, val[2]) |
|
1919 |
||
1920 |
k.clear_cache() |
|
1921 |
self.assertEqual({}, k._data._cache) |
|
1922 |
||
1923 |
val2 = read_one('text-2') |
|
1924 |
self.assertEqual(val, val2) |
|
1925 |
self.assertEqual({}, k._data._cache) |
|
1926 |
||
1927 |
def test_cache_read(self): |
|
1928 |
k = self.create_knit() |
|
1929 |
k.enable_cache() |
|
1930 |
||
1931 |
text = k.get_text('text-1') |
|
1932 |
self.assertEqual(TEXT_1, text) |
|
1933 |
self.assertEqual(['text-1'], k._data._cache.keys()) |
|
1934 |
||
1935 |
k.clear_cache() |
|
1936 |
self.assertEqual({}, k._data._cache) |
|
1937 |
||
1938 |
text = k.get_text('text-1') |
|
1939 |
self.assertEqual(TEXT_1, text) |
|
1940 |
self.assertEqual({}, k._data._cache) |
|
2102.2.1
by John Arbash Meinel
Fix bug #64789 _KnitIndex.add_versions() should dict compress new revisions |
1941 |
|
1942 |
||
1943 |
class TestKnitIndex(KnitTests): |
|
1944 |
||
1945 |
def test_add_versions_dictionary_compresses(self): |
|
1946 |
"""Adding versions to the index should update the lookup dict"""
|
|
1947 |
knit = self.make_test_knit() |
|
1948 |
idx = knit._index |
|
2670.2.2
by Robert Collins
* In ``bzrlib.knit`` the internal interface has been altered to use |
1949 |
idx.add_version('a-1', ['fulltext'], (None, 0, 0), []) |
2102.2.1
by John Arbash Meinel
Fix bug #64789 _KnitIndex.add_versions() should dict compress new revisions |
1950 |
self.check_file_contents('test.kndx', |
1951 |
'# bzr knit index 8\n' |
|
1952 |
'\n' |
|
1953 |
'a-1 fulltext 0 0 :'
|
|
1954 |
)
|
|
2670.2.2
by Robert Collins
* In ``bzrlib.knit`` the internal interface has been altered to use |
1955 |
idx.add_versions([('a-2', ['fulltext'], (None, 0, 0), ['a-1']), |
1956 |
('a-3', ['fulltext'], (None, 0, 0), ['a-2']), |
|
2102.2.1
by John Arbash Meinel
Fix bug #64789 _KnitIndex.add_versions() should dict compress new revisions |
1957 |
])
|
1958 |
self.check_file_contents('test.kndx', |
|
1959 |
'# bzr knit index 8\n' |
|
1960 |
'\n' |
|
1961 |
'a-1 fulltext 0 0 :\n' |
|
1962 |
'a-2 fulltext 0 0 0 :\n' |
|
1963 |
'a-3 fulltext 0 0 1 :'
|
|
1964 |
)
|
|
1965 |
self.assertEqual(['a-1', 'a-2', 'a-3'], idx._history) |
|
1966 |
self.assertEqual({'a-1':('a-1', ['fulltext'], 0, 0, [], 0), |
|
1967 |
'a-2':('a-2', ['fulltext'], 0, 0, ['a-1'], 1), |
|
1968 |
'a-3':('a-3', ['fulltext'], 0, 0, ['a-2'], 2), |
|
1969 |
}, idx._cache) |
|
1970 |
||
1971 |
def test_add_versions_fails_clean(self): |
|
1972 |
"""If add_versions fails in the middle, it restores a pristine state.
|
|
1973 |
||
1974 |
Any modifications that are made to the index are reset if all versions
|
|
1975 |
cannot be added.
|
|
1976 |
"""
|
|
1977 |
# This cheats a little bit by passing in a generator which will
|
|
1978 |
# raise an exception before the processing finishes
|
|
1979 |
# Other possibilities would be to have an version with the wrong number
|
|
1980 |
# of entries, or to make the backing transport unable to write any
|
|
1981 |
# files.
|
|
1982 |
||
1983 |
knit = self.make_test_knit() |
|
1984 |
idx = knit._index |
|
2670.2.2
by Robert Collins
* In ``bzrlib.knit`` the internal interface has been altered to use |
1985 |
idx.add_version('a-1', ['fulltext'], (None, 0, 0), []) |
2102.2.1
by John Arbash Meinel
Fix bug #64789 _KnitIndex.add_versions() should dict compress new revisions |
1986 |
|
1987 |
class StopEarly(Exception): |
|
1988 |
pass
|
|
1989 |
||
1990 |
def generate_failure(): |
|
1991 |
"""Add some entries and then raise an exception"""
|
|
2670.2.2
by Robert Collins
* In ``bzrlib.knit`` the internal interface has been altered to use |
1992 |
yield ('a-2', ['fulltext'], (None, 0, 0), ['a-1']) |
1993 |
yield ('a-3', ['fulltext'], (None, 0, 0), ['a-2']) |
|
2102.2.1
by John Arbash Meinel
Fix bug #64789 _KnitIndex.add_versions() should dict compress new revisions |
1994 |
raise StopEarly() |
1995 |
||
1996 |
# Assert the pre-condition
|
|
1997 |
self.assertEqual(['a-1'], idx._history) |
|
1998 |
self.assertEqual({'a-1':('a-1', ['fulltext'], 0, 0, [], 0)}, idx._cache) |
|
1999 |
||
2000 |
self.assertRaises(StopEarly, idx.add_versions, generate_failure()) |
|
2001 |
||
2002 |
# And it shouldn't be modified
|
|
2003 |
self.assertEqual(['a-1'], idx._history) |
|
2004 |
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. |
2005 |
|
2006 |
def test_knit_index_ignores_empty_files(self): |
|
2007 |
# There was a race condition in older bzr, where a ^C at the right time
|
|
2008 |
# could leave an empty .kndx file, which bzr would later claim was a
|
|
2009 |
# corrupted file since the header was not present. In reality, the file
|
|
2010 |
# just wasn't created, so it should be ignored.
|
|
2011 |
t = get_transport('.') |
|
2012 |
t.put_bytes('test.kndx', '') |
|
2013 |
||
2014 |
knit = self.make_test_knit() |
|
2015 |
||
2016 |
def test_knit_index_checks_header(self): |
|
2017 |
t = get_transport('.') |
|
2018 |
t.put_bytes('test.kndx', '# not really a knit header\n\n') |
|
2019 |
||
2196.2.1
by John Arbash Meinel
Merge Dmitry's optimizations and minimize the actual diff. |
2020 |
self.assertRaises(KnitHeaderError, self.make_test_knit) |
2625.8.1
by Robert Collins
LIBRARY API BREAKS: |
2021 |
|
2022 |
||
2023 |
class TestGraphIndexKnit(KnitTests): |
|
2024 |
"""Tests for knits using a GraphIndex rather than a KnitIndex."""
|
|
2025 |
||
2026 |
def make_g_index(self, name, ref_lists=0, nodes=[]): |
|
2027 |
builder = GraphIndexBuilder(ref_lists) |
|
2028 |
for node, references, value in nodes: |
|
2029 |
builder.add_node(node, references, value) |
|
2030 |
stream = builder.finish() |
|
2031 |
trans = self.get_transport() |
|
2032 |
trans.put_file(name, stream) |
|
2033 |
return GraphIndex(trans, name) |
|
2034 |
||
2035 |
def two_graph_index(self, deltas=False, catch_adds=False): |
|
2036 |
"""Build a two-graph index.
|
|
2037 |
||
2038 |
:param deltas: If true, use underlying indices with two node-ref
|
|
2039 |
lists and 'parent' set to a delta-compressed against tail.
|
|
2040 |
"""
|
|
2041 |
# build a complex graph across several indices.
|
|
2042 |
if deltas: |
|
2624.2.5
by Robert Collins
Change bzrlib.index.Index keys to be 1-tuples, not strings. |
2043 |
# delta compression inn the index
|
2625.8.1
by Robert Collins
LIBRARY API BREAKS: |
2044 |
index1 = self.make_g_index('1', 2, [ |
2624.2.5
by Robert Collins
Change bzrlib.index.Index keys to be 1-tuples, not strings. |
2045 |
(('tip', ), 'N0 100', ([('parent', )], [], )), |
2046 |
(('tail', ), '', ([], []))]) |
|
2625.8.1
by Robert Collins
LIBRARY API BREAKS: |
2047 |
index2 = self.make_g_index('2', 2, [ |
2624.2.5
by Robert Collins
Change bzrlib.index.Index keys to be 1-tuples, not strings. |
2048 |
(('parent', ), ' 100 78', ([('tail', ), ('ghost', )], [('tail', )])), |
2049 |
(('separate', ), '', ([], []))]) |
|
2625.8.1
by Robert Collins
LIBRARY API BREAKS: |
2050 |
else: |
2624.2.5
by Robert Collins
Change bzrlib.index.Index keys to be 1-tuples, not strings. |
2051 |
# just blob location and graph in the index.
|
2625.8.1
by Robert Collins
LIBRARY API BREAKS: |
2052 |
index1 = self.make_g_index('1', 1, [ |
2624.2.5
by Robert Collins
Change bzrlib.index.Index keys to be 1-tuples, not strings. |
2053 |
(('tip', ), 'N0 100', ([('parent', )], )), |
2054 |
(('tail', ), '', ([], ))]) |
|
2625.8.1
by Robert Collins
LIBRARY API BREAKS: |
2055 |
index2 = self.make_g_index('2', 1, [ |
2624.2.5
by Robert Collins
Change bzrlib.index.Index keys to be 1-tuples, not strings. |
2056 |
(('parent', ), ' 100 78', ([('tail', ), ('ghost', )], )), |
2057 |
(('separate', ), '', ([], ))]) |
|
2625.8.1
by Robert Collins
LIBRARY API BREAKS: |
2058 |
combined_index = CombinedGraphIndex([index1, index2]) |
2059 |
if catch_adds: |
|
2060 |
self.combined_index = combined_index |
|
2061 |
self.caught_entries = [] |
|
2062 |
add_callback = self.catch_add |
|
2063 |
else: |
|
2064 |
add_callback = None |
|
2065 |
return KnitGraphIndex(combined_index, deltas=deltas, |
|
2066 |
add_callback=add_callback) |
|
2067 |
||
2068 |
def test_get_graph(self): |
|
2069 |
index = self.two_graph_index() |
|
2070 |
self.assertEqual(set([ |
|
2071 |
('tip', ('parent', )), |
|
2072 |
('tail', ()), |
|
2073 |
('parent', ('tail', 'ghost')), |
|
2074 |
('separate', ()), |
|
2075 |
]), set(index.get_graph())) |
|
2076 |
||
2077 |
def test_get_ancestry(self): |
|
2078 |
# get_ancestry is defined as eliding ghosts, not erroring.
|
|
2079 |
index = self.two_graph_index() |
|
2080 |
self.assertEqual([], index.get_ancestry([])) |
|
2081 |
self.assertEqual(['separate'], index.get_ancestry(['separate'])) |
|
2082 |
self.assertEqual(['tail'], index.get_ancestry(['tail'])) |
|
2083 |
self.assertEqual(['tail', 'parent'], index.get_ancestry(['parent'])) |
|
2084 |
self.assertEqual(['tail', 'parent', 'tip'], index.get_ancestry(['tip'])) |
|
2085 |
self.assertTrue(index.get_ancestry(['tip', 'separate']) in |
|
2086 |
(['tail', 'parent', 'tip', 'separate'], |
|
2087 |
['separate', 'tail', 'parent', 'tip'], |
|
2088 |
))
|
|
2089 |
# and without topo_sort
|
|
2090 |
self.assertEqual(set(['separate']), |
|
2091 |
set(index.get_ancestry(['separate'], topo_sorted=False))) |
|
2092 |
self.assertEqual(set(['tail']), |
|
2093 |
set(index.get_ancestry(['tail'], topo_sorted=False))) |
|
2094 |
self.assertEqual(set(['tail', 'parent']), |
|
2095 |
set(index.get_ancestry(['parent'], topo_sorted=False))) |
|
2096 |
self.assertEqual(set(['tail', 'parent', 'tip']), |
|
2097 |
set(index.get_ancestry(['tip'], topo_sorted=False))) |
|
2098 |
self.assertEqual(set(['separate', 'tail', 'parent', 'tip']), |
|
2099 |
set(index.get_ancestry(['tip', 'separate']))) |
|
2100 |
# asking for a ghost makes it go boom.
|
|
2101 |
self.assertRaises(errors.RevisionNotPresent, index.get_ancestry, ['ghost']) |
|
2102 |
||
2103 |
def test_get_ancestry_with_ghosts(self): |
|
2104 |
index = self.two_graph_index() |
|
2105 |
self.assertEqual([], index.get_ancestry_with_ghosts([])) |
|
2106 |
self.assertEqual(['separate'], index.get_ancestry_with_ghosts(['separate'])) |
|
2107 |
self.assertEqual(['tail'], index.get_ancestry_with_ghosts(['tail'])) |
|
2108 |
self.assertTrue(index.get_ancestry_with_ghosts(['parent']) in |
|
2109 |
(['tail', 'ghost', 'parent'], |
|
2110 |
['ghost', 'tail', 'parent'], |
|
2111 |
))
|
|
2112 |
self.assertTrue(index.get_ancestry_with_ghosts(['tip']) in |
|
2113 |
(['tail', 'ghost', 'parent', 'tip'], |
|
2114 |
['ghost', 'tail', 'parent', 'tip'], |
|
2115 |
))
|
|
2116 |
self.assertTrue(index.get_ancestry_with_ghosts(['tip', 'separate']) in |
|
2117 |
(['tail', 'ghost', 'parent', 'tip', 'separate'], |
|
2118 |
['ghost', 'tail', 'parent', 'tip', 'separate'], |
|
2119 |
['separate', 'tail', 'ghost', 'parent', 'tip'], |
|
2120 |
['separate', 'ghost', 'tail', 'parent', 'tip'], |
|
2121 |
))
|
|
2122 |
# asking for a ghost makes it go boom.
|
|
2123 |
self.assertRaises(errors.RevisionNotPresent, index.get_ancestry_with_ghosts, ['ghost']) |
|
2124 |
||
2125 |
def test_num_versions(self): |
|
2126 |
index = self.two_graph_index() |
|
2127 |
self.assertEqual(4, index.num_versions()) |
|
2128 |
||
2129 |
def test_get_versions(self): |
|
2130 |
index = self.two_graph_index() |
|
2131 |
self.assertEqual(set(['tail', 'tip', 'parent', 'separate']), |
|
2132 |
set(index.get_versions())) |
|
2133 |
||
2134 |
def test_has_version(self): |
|
2135 |
index = self.two_graph_index() |
|
2136 |
self.assertTrue(index.has_version('tail')) |
|
2137 |
self.assertFalse(index.has_version('ghost')) |
|
2138 |
||
2139 |
def test_get_position(self): |
|
2140 |
index = self.two_graph_index() |
|
2670.2.2
by Robert Collins
* In ``bzrlib.knit`` the internal interface has been altered to use |
2141 |
self.assertEqual((index._graph_index._indices[0], 0, 100), index.get_position('tip')) |
2142 |
self.assertEqual((index._graph_index._indices[1], 100, 78), index.get_position('parent')) |
|
2625.8.1
by Robert Collins
LIBRARY API BREAKS: |
2143 |
|
2144 |
def test_get_method_deltas(self): |
|
2145 |
index = self.two_graph_index(deltas=True) |
|
2146 |
self.assertEqual('fulltext', index.get_method('tip')) |
|
2147 |
self.assertEqual('line-delta', index.get_method('parent')) |
|
2148 |
||
2149 |
def test_get_method_no_deltas(self): |
|
2150 |
# check that the parent-history lookup is ignored with deltas=False.
|
|
2151 |
index = self.two_graph_index(deltas=False) |
|
2152 |
self.assertEqual('fulltext', index.get_method('tip')) |
|
2153 |
self.assertEqual('fulltext', index.get_method('parent')) |
|
2154 |
||
2155 |
def test_get_options_deltas(self): |
|
2156 |
index = self.two_graph_index(deltas=True) |
|
2658.2.1
by Robert Collins
Fix mismatch between KnitGraphIndex and KnitIndex in get_options. |
2157 |
self.assertEqual(['fulltext', 'no-eol'], index.get_options('tip')) |
2158 |
self.assertEqual(['line-delta'], index.get_options('parent')) |
|
2625.8.1
by Robert Collins
LIBRARY API BREAKS: |
2159 |
|
2160 |
def test_get_options_no_deltas(self): |
|
2161 |
# check that the parent-history lookup is ignored with deltas=False.
|
|
2162 |
index = self.two_graph_index(deltas=False) |
|
2658.2.1
by Robert Collins
Fix mismatch between KnitGraphIndex and KnitIndex in get_options. |
2163 |
self.assertEqual(['fulltext', 'no-eol'], index.get_options('tip')) |
2164 |
self.assertEqual(['fulltext'], index.get_options('parent')) |
|
2625.8.1
by Robert Collins
LIBRARY API BREAKS: |
2165 |
|
2166 |
def test_get_parents(self): |
|
2167 |
# get_parents ignores ghosts
|
|
2168 |
index = self.two_graph_index() |
|
2169 |
self.assertEqual(('tail', ), index.get_parents('parent')) |
|
2170 |
# and errors on ghosts.
|
|
2171 |
self.assertRaises(errors.RevisionNotPresent, |
|
2172 |
index.get_parents, 'ghost') |
|
2173 |
||
2174 |
def test_get_parents_with_ghosts(self): |
|
2175 |
index = self.two_graph_index() |
|
2176 |
self.assertEqual(('tail', 'ghost'), index.get_parents_with_ghosts('parent')) |
|
2177 |
# and errors on ghosts.
|
|
2178 |
self.assertRaises(errors.RevisionNotPresent, |
|
2179 |
index.get_parents_with_ghosts, 'ghost') |
|
2180 |
||
2181 |
def test_check_versions_present(self): |
|
2182 |
# ghosts should not be considered present
|
|
2183 |
index = self.two_graph_index() |
|
2184 |
self.assertRaises(RevisionNotPresent, index.check_versions_present, |
|
2185 |
['ghost']) |
|
2186 |
self.assertRaises(RevisionNotPresent, index.check_versions_present, |
|
2187 |
['tail', 'ghost']) |
|
2188 |
index.check_versions_present(['tail', 'separate']) |
|
2189 |
||
2190 |
def catch_add(self, entries): |
|
2191 |
self.caught_entries.append(entries) |
|
2192 |
||
2193 |
def test_add_no_callback_errors(self): |
|
2194 |
index = self.two_graph_index() |
|
2195 |
self.assertRaises(errors.ReadOnlyError, index.add_version, |
|
2670.2.2
by Robert Collins
* In ``bzrlib.knit`` the internal interface has been altered to use |
2196 |
'new', 'fulltext,no-eol', (None, 50, 60), ['separate']) |
2625.8.1
by Robert Collins
LIBRARY API BREAKS: |
2197 |
|
2198 |
def test_add_version_smoke(self): |
|
2199 |
index = self.two_graph_index(catch_adds=True) |
|
2670.2.2
by Robert Collins
* In ``bzrlib.knit`` the internal interface has been altered to use |
2200 |
index.add_version('new', 'fulltext,no-eol', (None, 50, 60), ['separate']) |
2624.2.5
by Robert Collins
Change bzrlib.index.Index keys to be 1-tuples, not strings. |
2201 |
self.assertEqual([[(('new', ), 'N50 60', ((('separate',),),))]], |
2625.8.1
by Robert Collins
LIBRARY API BREAKS: |
2202 |
self.caught_entries) |
2203 |
||
2204 |
def test_add_version_delta_not_delta_index(self): |
|
2205 |
index = self.two_graph_index(catch_adds=True) |
|
2206 |
self.assertRaises(errors.KnitCorrupt, index.add_version, |
|
2670.2.2
by Robert Collins
* In ``bzrlib.knit`` the internal interface has been altered to use |
2207 |
'new', 'no-eol,line-delta', (None, 0, 100), ['parent']) |
2625.8.1
by Robert Collins
LIBRARY API BREAKS: |
2208 |
self.assertEqual([], self.caught_entries) |
2209 |
||
2210 |
def test_add_version_same_dup(self): |
|
2211 |
index = self.two_graph_index(catch_adds=True) |
|
2212 |
# options can be spelt two different ways
|
|
2670.2.2
by Robert Collins
* In ``bzrlib.knit`` the internal interface has been altered to use |
2213 |
index.add_version('tip', 'fulltext,no-eol', (None, 0, 100), ['parent']) |
2214 |
index.add_version('tip', 'no-eol,fulltext', (None, 0, 100), ['parent']) |
|
2625.8.1
by Robert Collins
LIBRARY API BREAKS: |
2215 |
# but neither should have added data.
|
2216 |
self.assertEqual([[], []], self.caught_entries) |
|
2217 |
||
2218 |
def test_add_version_different_dup(self): |
|
2219 |
index = self.two_graph_index(deltas=True, catch_adds=True) |
|
2220 |
# change options
|
|
2221 |
self.assertRaises(errors.KnitCorrupt, index.add_version, |
|
2670.2.2
by Robert Collins
* In ``bzrlib.knit`` the internal interface has been altered to use |
2222 |
'tip', 'no-eol,line-delta', (None, 0, 100), ['parent']) |
2223 |
self.assertRaises(errors.KnitCorrupt, index.add_version, |
|
2224 |
'tip', 'line-delta,no-eol', (None, 0, 100), ['parent']) |
|
2225 |
self.assertRaises(errors.KnitCorrupt, index.add_version, |
|
2226 |
'tip', 'fulltext', (None, 0, 100), ['parent']) |
|
2625.8.1
by Robert Collins
LIBRARY API BREAKS: |
2227 |
# position/length
|
2228 |
self.assertRaises(errors.KnitCorrupt, index.add_version, |
|
2670.2.2
by Robert Collins
* In ``bzrlib.knit`` the internal interface has been altered to use |
2229 |
'tip', 'fulltext,no-eol', (None, 50, 100), ['parent']) |
2625.8.1
by Robert Collins
LIBRARY API BREAKS: |
2230 |
self.assertRaises(errors.KnitCorrupt, index.add_version, |
2670.2.2
by Robert Collins
* In ``bzrlib.knit`` the internal interface has been altered to use |
2231 |
'tip', 'fulltext,no-eol', (None, 0, 1000), ['parent']) |
2625.8.1
by Robert Collins
LIBRARY API BREAKS: |
2232 |
# parents
|
2233 |
self.assertRaises(errors.KnitCorrupt, index.add_version, |
|
2670.2.2
by Robert Collins
* In ``bzrlib.knit`` the internal interface has been altered to use |
2234 |
'tip', 'fulltext,no-eol', (None, 0, 100), []) |
2625.8.1
by Robert Collins
LIBRARY API BREAKS: |
2235 |
self.assertEqual([], self.caught_entries) |
2236 |
||
2237 |
def test_add_versions_nodeltas(self): |
|
2238 |
index = self.two_graph_index(catch_adds=True) |
|
2239 |
index.add_versions([ |
|
2670.2.2
by Robert Collins
* In ``bzrlib.knit`` the internal interface has been altered to use |
2240 |
('new', 'fulltext,no-eol', (None, 50, 60), ['separate']), |
2241 |
('new2', 'fulltext', (None, 0, 6), ['new']), |
|
2625.8.1
by Robert Collins
LIBRARY API BREAKS: |
2242 |
])
|
2624.2.5
by Robert Collins
Change bzrlib.index.Index keys to be 1-tuples, not strings. |
2243 |
self.assertEqual([(('new', ), 'N50 60', ((('separate',),),)), |
2244 |
(('new2', ), ' 0 6', ((('new',),),))], |
|
2625.8.1
by Robert Collins
LIBRARY API BREAKS: |
2245 |
sorted(self.caught_entries[0])) |
2246 |
self.assertEqual(1, len(self.caught_entries)) |
|
2247 |
||
2248 |
def test_add_versions_deltas(self): |
|
2249 |
index = self.two_graph_index(deltas=True, catch_adds=True) |
|
2250 |
index.add_versions([ |
|
2670.2.2
by Robert Collins
* In ``bzrlib.knit`` the internal interface has been altered to use |
2251 |
('new', 'fulltext,no-eol', (None, 50, 60), ['separate']), |
2252 |
('new2', 'line-delta', (None, 0, 6), ['new']), |
|
2625.8.1
by Robert Collins
LIBRARY API BREAKS: |
2253 |
])
|
2624.2.5
by Robert Collins
Change bzrlib.index.Index keys to be 1-tuples, not strings. |
2254 |
self.assertEqual([(('new', ), 'N50 60', ((('separate',),), ())), |
2255 |
(('new2', ), ' 0 6', ((('new',),), (('new',),), ))], |
|
2625.8.1
by Robert Collins
LIBRARY API BREAKS: |
2256 |
sorted(self.caught_entries[0])) |
2257 |
self.assertEqual(1, len(self.caught_entries)) |
|
2258 |
||
2259 |
def test_add_versions_delta_not_delta_index(self): |
|
2260 |
index = self.two_graph_index(catch_adds=True) |
|
2261 |
self.assertRaises(errors.KnitCorrupt, index.add_versions, |
|
2670.2.2
by Robert Collins
* In ``bzrlib.knit`` the internal interface has been altered to use |
2262 |
[('new', 'no-eol,line-delta', (None, 0, 100), ['parent'])]) |
2625.8.1
by Robert Collins
LIBRARY API BREAKS: |
2263 |
self.assertEqual([], self.caught_entries) |
2264 |
||
2265 |
def test_add_versions_same_dup(self): |
|
2266 |
index = self.two_graph_index(catch_adds=True) |
|
2267 |
# options can be spelt two different ways
|
|
2670.2.2
by Robert Collins
* In ``bzrlib.knit`` the internal interface has been altered to use |
2268 |
index.add_versions([('tip', 'fulltext,no-eol', (None, 0, 100), ['parent'])]) |
2269 |
index.add_versions([('tip', 'no-eol,fulltext', (None, 0, 100), ['parent'])]) |
|
2625.8.1
by Robert Collins
LIBRARY API BREAKS: |
2270 |
# but neither should have added data.
|
2271 |
self.assertEqual([[], []], self.caught_entries) |
|
2272 |
||
2273 |
def test_add_versions_different_dup(self): |
|
2274 |
index = self.two_graph_index(deltas=True, catch_adds=True) |
|
2275 |
# change options
|
|
2276 |
self.assertRaises(errors.KnitCorrupt, index.add_versions, |
|
2670.2.2
by Robert Collins
* In ``bzrlib.knit`` the internal interface has been altered to use |
2277 |
[('tip', 'no-eol,line-delta', (None, 0, 100), ['parent'])]) |
2278 |
self.assertRaises(errors.KnitCorrupt, index.add_versions, |
|
2279 |
[('tip', 'line-delta,no-eol', (None, 0, 100), ['parent'])]) |
|
2280 |
self.assertRaises(errors.KnitCorrupt, index.add_versions, |
|
2281 |
[('tip', 'fulltext', (None, 0, 100), ['parent'])]) |
|
2625.8.1
by Robert Collins
LIBRARY API BREAKS: |
2282 |
# position/length
|
2283 |
self.assertRaises(errors.KnitCorrupt, index.add_versions, |
|
2670.2.2
by Robert Collins
* In ``bzrlib.knit`` the internal interface has been altered to use |
2284 |
[('tip', 'fulltext,no-eol', (None, 50, 100), ['parent'])]) |
2625.8.1
by Robert Collins
LIBRARY API BREAKS: |
2285 |
self.assertRaises(errors.KnitCorrupt, index.add_versions, |
2670.2.2
by Robert Collins
* In ``bzrlib.knit`` the internal interface has been altered to use |
2286 |
[('tip', 'fulltext,no-eol', (None, 0, 1000), ['parent'])]) |
2625.8.1
by Robert Collins
LIBRARY API BREAKS: |
2287 |
# parents
|
2288 |
self.assertRaises(errors.KnitCorrupt, index.add_versions, |
|
2670.2.2
by Robert Collins
* In ``bzrlib.knit`` the internal interface has been altered to use |
2289 |
[('tip', 'fulltext,no-eol', (None, 0, 100), [])]) |
2625.8.1
by Robert Collins
LIBRARY API BREAKS: |
2290 |
# change options in the second record
|
2291 |
self.assertRaises(errors.KnitCorrupt, index.add_versions, |
|
2670.2.2
by Robert Collins
* In ``bzrlib.knit`` the internal interface has been altered to use |
2292 |
[('tip', 'fulltext,no-eol', (None, 0, 100), ['parent']), |
2293 |
('tip', 'no-eol,line-delta', (None, 0, 100), ['parent'])]) |
|
2625.8.1
by Robert Collins
LIBRARY API BREAKS: |
2294 |
self.assertEqual([], self.caught_entries) |
2295 |
||
2296 |
def test_iter_parents(self): |
|
2297 |
index1 = self.make_g_index('1', 1, [ |
|
2298 |
# no parents
|
|
2624.2.5
by Robert Collins
Change bzrlib.index.Index keys to be 1-tuples, not strings. |
2299 |
(('r0', ), 'N0 100', ([], )), |
2625.8.1
by Robert Collins
LIBRARY API BREAKS: |
2300 |
# 1 parent
|
2624.2.5
by Robert Collins
Change bzrlib.index.Index keys to be 1-tuples, not strings. |
2301 |
(('r1', ), '', ([('r0', )], ))]) |
2625.8.1
by Robert Collins
LIBRARY API BREAKS: |
2302 |
index2 = self.make_g_index('2', 1, [ |
2303 |
# 2 parents
|
|
2624.2.5
by Robert Collins
Change bzrlib.index.Index keys to be 1-tuples, not strings. |
2304 |
(('r2', ), 'N0 100', ([('r1', ), ('r0', )], )), |
2625.8.1
by Robert Collins
LIBRARY API BREAKS: |
2305 |
])
|
2306 |
combined_index = CombinedGraphIndex([index1, index2]) |
|
2307 |
index = KnitGraphIndex(combined_index) |
|
2308 |
# XXX TODO a ghost
|
|
2309 |
# cases: each sample data individually:
|
|
2310 |
self.assertEqual(set([('r0', ())]), |
|
2311 |
set(index.iter_parents(['r0']))) |
|
2312 |
self.assertEqual(set([('r1', ('r0', ))]), |
|
2313 |
set(index.iter_parents(['r1']))) |
|
2314 |
self.assertEqual(set([('r2', ('r1', 'r0'))]), |
|
2315 |
set(index.iter_parents(['r2']))) |
|
2316 |
# no nodes returned for a missing node
|
|
2317 |
self.assertEqual(set(), |
|
2318 |
set(index.iter_parents(['missing']))) |
|
2319 |
# 1 node returned with missing nodes skipped
|
|
2320 |
self.assertEqual(set([('r1', ('r0', ))]), |
|
2321 |
set(index.iter_parents(['ghost1', 'r1', 'ghost']))) |
|
2322 |
# 2 nodes returned
|
|
2323 |
self.assertEqual(set([('r0', ()), ('r1', ('r0', ))]), |
|
2324 |
set(index.iter_parents(['r0', 'r1']))) |
|
2325 |
# 2 nodes returned, missing skipped
|
|
2326 |
self.assertEqual(set([('r0', ()), ('r1', ('r0', ))]), |
|
2327 |
set(index.iter_parents(['a', 'r0', 'b', 'r1', 'c']))) |
|
2328 |
||
2329 |
||
2330 |
class TestNoParentsGraphIndexKnit(KnitTests): |
|
2331 |
"""Tests for knits using KnitGraphIndex with no parents."""
|
|
2332 |
||
2333 |
def make_g_index(self, name, ref_lists=0, nodes=[]): |
|
2334 |
builder = GraphIndexBuilder(ref_lists) |
|
2335 |
for node, references in nodes: |
|
2336 |
builder.add_node(node, references) |
|
2337 |
stream = builder.finish() |
|
2338 |
trans = self.get_transport() |
|
2339 |
trans.put_file(name, stream) |
|
2340 |
return GraphIndex(trans, name) |
|
2341 |
||
2342 |
def test_parents_deltas_incompatible(self): |
|
2343 |
index = CombinedGraphIndex([]) |
|
2344 |
self.assertRaises(errors.KnitError, KnitGraphIndex, index, |
|
2345 |
deltas=True, parents=False) |
|
2346 |
||
2347 |
def two_graph_index(self, catch_adds=False): |
|
2348 |
"""Build a two-graph index.
|
|
2349 |
||
2350 |
:param deltas: If true, use underlying indices with two node-ref
|
|
2351 |
lists and 'parent' set to a delta-compressed against tail.
|
|
2352 |
"""
|
|
2353 |
# put several versions in the index.
|
|
2354 |
index1 = self.make_g_index('1', 0, [ |
|
2624.2.5
by Robert Collins
Change bzrlib.index.Index keys to be 1-tuples, not strings. |
2355 |
(('tip', ), 'N0 100'), |
2356 |
(('tail', ), '')]) |
|
2625.8.1
by Robert Collins
LIBRARY API BREAKS: |
2357 |
index2 = self.make_g_index('2', 0, [ |
2624.2.5
by Robert Collins
Change bzrlib.index.Index keys to be 1-tuples, not strings. |
2358 |
(('parent', ), ' 100 78'), |
2359 |
(('separate', ), '')]) |
|
2625.8.1
by Robert Collins
LIBRARY API BREAKS: |
2360 |
combined_index = CombinedGraphIndex([index1, index2]) |
2361 |
if catch_adds: |
|
2362 |
self.combined_index = combined_index |
|
2363 |
self.caught_entries = [] |
|
2364 |
add_callback = self.catch_add |
|
2365 |
else: |
|
2366 |
add_callback = None |
|
2367 |
return KnitGraphIndex(combined_index, parents=False, |
|
2368 |
add_callback=add_callback) |
|
2369 |
||
2370 |
def test_get_graph(self): |
|
2371 |
index = self.two_graph_index() |
|
2372 |
self.assertEqual(set([ |
|
2373 |
('tip', ()), |
|
2374 |
('tail', ()), |
|
2375 |
('parent', ()), |
|
2376 |
('separate', ()), |
|
2377 |
]), set(index.get_graph())) |
|
2378 |
||
2379 |
def test_get_ancestry(self): |
|
2380 |
# with no parents, ancestry is always just the key.
|
|
2381 |
index = self.two_graph_index() |
|
2382 |
self.assertEqual([], index.get_ancestry([])) |
|
2383 |
self.assertEqual(['separate'], index.get_ancestry(['separate'])) |
|
2384 |
self.assertEqual(['tail'], index.get_ancestry(['tail'])) |
|
2385 |
self.assertEqual(['parent'], index.get_ancestry(['parent'])) |
|
2386 |
self.assertEqual(['tip'], index.get_ancestry(['tip'])) |
|
2387 |
self.assertTrue(index.get_ancestry(['tip', 'separate']) in |
|
2388 |
(['tip', 'separate'], |
|
2389 |
['separate', 'tip'], |
|
2390 |
))
|
|
2391 |
# asking for a ghost makes it go boom.
|
|
2392 |
self.assertRaises(errors.RevisionNotPresent, index.get_ancestry, ['ghost']) |
|
2393 |
||
2394 |
def test_get_ancestry_with_ghosts(self): |
|
2395 |
index = self.two_graph_index() |
|
2396 |
self.assertEqual([], index.get_ancestry_with_ghosts([])) |
|
2397 |
self.assertEqual(['separate'], index.get_ancestry_with_ghosts(['separate'])) |
|
2398 |
self.assertEqual(['tail'], index.get_ancestry_with_ghosts(['tail'])) |
|
2399 |
self.assertEqual(['parent'], index.get_ancestry_with_ghosts(['parent'])) |
|
2400 |
self.assertEqual(['tip'], index.get_ancestry_with_ghosts(['tip'])) |
|
2401 |
self.assertTrue(index.get_ancestry_with_ghosts(['tip', 'separate']) in |
|
2402 |
(['tip', 'separate'], |
|
2403 |
['separate', 'tip'], |
|
2404 |
))
|
|
2405 |
# asking for a ghost makes it go boom.
|
|
2406 |
self.assertRaises(errors.RevisionNotPresent, index.get_ancestry_with_ghosts, ['ghost']) |
|
2407 |
||
2408 |
def test_num_versions(self): |
|
2409 |
index = self.two_graph_index() |
|
2410 |
self.assertEqual(4, index.num_versions()) |
|
2411 |
||
2412 |
def test_get_versions(self): |
|
2413 |
index = self.two_graph_index() |
|
2414 |
self.assertEqual(set(['tail', 'tip', 'parent', 'separate']), |
|
2415 |
set(index.get_versions())) |
|
2416 |
||
2417 |
def test_has_version(self): |
|
2418 |
index = self.two_graph_index() |
|
2419 |
self.assertTrue(index.has_version('tail')) |
|
2420 |
self.assertFalse(index.has_version('ghost')) |
|
2421 |
||
2422 |
def test_get_position(self): |
|
2423 |
index = self.two_graph_index() |
|
2670.2.2
by Robert Collins
* In ``bzrlib.knit`` the internal interface has been altered to use |
2424 |
self.assertEqual((index._graph_index._indices[0], 0, 100), index.get_position('tip')) |
2425 |
self.assertEqual((index._graph_index._indices[1], 100, 78), index.get_position('parent')) |
|
2625.8.1
by Robert Collins
LIBRARY API BREAKS: |
2426 |
|
2427 |
def test_get_method(self): |
|
2428 |
index = self.two_graph_index() |
|
2429 |
self.assertEqual('fulltext', index.get_method('tip')) |
|
2658.2.1
by Robert Collins
Fix mismatch between KnitGraphIndex and KnitIndex in get_options. |
2430 |
self.assertEqual(['fulltext'], index.get_options('parent')) |
2625.8.1
by Robert Collins
LIBRARY API BREAKS: |
2431 |
|
2432 |
def test_get_options(self): |
|
2433 |
index = self.two_graph_index() |
|
2658.2.1
by Robert Collins
Fix mismatch between KnitGraphIndex and KnitIndex in get_options. |
2434 |
self.assertEqual(['fulltext', 'no-eol'], index.get_options('tip')) |
2435 |
self.assertEqual(['fulltext'], index.get_options('parent')) |
|
2625.8.1
by Robert Collins
LIBRARY API BREAKS: |
2436 |
|
2437 |
def test_get_parents(self): |
|
2438 |
index = self.two_graph_index() |
|
2439 |
self.assertEqual((), index.get_parents('parent')) |
|
2440 |
# and errors on ghosts.
|
|
2441 |
self.assertRaises(errors.RevisionNotPresent, |
|
2442 |
index.get_parents, 'ghost') |
|
2443 |
||
2444 |
def test_get_parents_with_ghosts(self): |
|
2445 |
index = self.two_graph_index() |
|
2446 |
self.assertEqual((), index.get_parents_with_ghosts('parent')) |
|
2447 |
# and errors on ghosts.
|
|
2448 |
self.assertRaises(errors.RevisionNotPresent, |
|
2449 |
index.get_parents_with_ghosts, 'ghost') |
|
2450 |
||
2451 |
def test_check_versions_present(self): |
|
2452 |
index = self.two_graph_index() |
|
2453 |
self.assertRaises(RevisionNotPresent, index.check_versions_present, |
|
2454 |
['missing']) |
|
2455 |
self.assertRaises(RevisionNotPresent, index.check_versions_present, |
|
2456 |
['tail', 'missing']) |
|
2457 |
index.check_versions_present(['tail', 'separate']) |
|
2458 |
||
2459 |
def catch_add(self, entries): |
|
2460 |
self.caught_entries.append(entries) |
|
2461 |
||
2462 |
def test_add_no_callback_errors(self): |
|
2463 |
index = self.two_graph_index() |
|
2464 |
self.assertRaises(errors.ReadOnlyError, index.add_version, |
|
2670.2.2
by Robert Collins
* In ``bzrlib.knit`` the internal interface has been altered to use |
2465 |
'new', 'fulltext,no-eol', (None, 50, 60), ['separate']) |
2625.8.1
by Robert Collins
LIBRARY API BREAKS: |
2466 |
|
2467 |
def test_add_version_smoke(self): |
|
2468 |
index = self.two_graph_index(catch_adds=True) |
|
2670.2.2
by Robert Collins
* In ``bzrlib.knit`` the internal interface has been altered to use |
2469 |
index.add_version('new', 'fulltext,no-eol', (None, 50, 60), []) |
2624.2.5
by Robert Collins
Change bzrlib.index.Index keys to be 1-tuples, not strings. |
2470 |
self.assertEqual([[(('new', ), 'N50 60')]], |
2625.8.1
by Robert Collins
LIBRARY API BREAKS: |
2471 |
self.caught_entries) |
2472 |
||
2473 |
def test_add_version_delta_not_delta_index(self): |
|
2474 |
index = self.two_graph_index(catch_adds=True) |
|
2475 |
self.assertRaises(errors.KnitCorrupt, index.add_version, |
|
2670.2.2
by Robert Collins
* In ``bzrlib.knit`` the internal interface has been altered to use |
2476 |
'new', 'no-eol,line-delta', (None, 0, 100), []) |
2625.8.1
by Robert Collins
LIBRARY API BREAKS: |
2477 |
self.assertEqual([], self.caught_entries) |
2478 |
||
2479 |
def test_add_version_same_dup(self): |
|
2480 |
index = self.two_graph_index(catch_adds=True) |
|
2481 |
# options can be spelt two different ways
|
|
2670.2.2
by Robert Collins
* In ``bzrlib.knit`` the internal interface has been altered to use |
2482 |
index.add_version('tip', 'fulltext,no-eol', (None, 0, 100), []) |
2483 |
index.add_version('tip', 'no-eol,fulltext', (None, 0, 100), []) |
|
2625.8.1
by Robert Collins
LIBRARY API BREAKS: |
2484 |
# but neither should have added data.
|
2485 |
self.assertEqual([[], []], self.caught_entries) |
|
2486 |
||
2487 |
def test_add_version_different_dup(self): |
|
2488 |
index = self.two_graph_index(catch_adds=True) |
|
2489 |
# change options
|
|
2490 |
self.assertRaises(errors.KnitCorrupt, index.add_version, |
|
2670.2.2
by Robert Collins
* In ``bzrlib.knit`` the internal interface has been altered to use |
2491 |
'tip', 'no-eol,line-delta', (None, 0, 100), []) |
2492 |
self.assertRaises(errors.KnitCorrupt, index.add_version, |
|
2493 |
'tip', 'line-delta,no-eol', (None, 0, 100), []) |
|
2494 |
self.assertRaises(errors.KnitCorrupt, index.add_version, |
|
2495 |
'tip', 'fulltext', (None, 0, 100), []) |
|
2625.8.1
by Robert Collins
LIBRARY API BREAKS: |
2496 |
# position/length
|
2497 |
self.assertRaises(errors.KnitCorrupt, index.add_version, |
|
2670.2.2
by Robert Collins
* In ``bzrlib.knit`` the internal interface has been altered to use |
2498 |
'tip', 'fulltext,no-eol', (None, 50, 100), []) |
2625.8.1
by Robert Collins
LIBRARY API BREAKS: |
2499 |
self.assertRaises(errors.KnitCorrupt, index.add_version, |
2670.2.2
by Robert Collins
* In ``bzrlib.knit`` the internal interface has been altered to use |
2500 |
'tip', 'fulltext,no-eol', (None, 0, 1000), []) |
2625.8.1
by Robert Collins
LIBRARY API BREAKS: |
2501 |
# parents
|
2502 |
self.assertRaises(errors.KnitCorrupt, index.add_version, |
|
2670.2.2
by Robert Collins
* In ``bzrlib.knit`` the internal interface has been altered to use |
2503 |
'tip', 'fulltext,no-eol', (None, 0, 100), ['parent']) |
2625.8.1
by Robert Collins
LIBRARY API BREAKS: |
2504 |
self.assertEqual([], self.caught_entries) |
2505 |
||
2506 |
def test_add_versions(self): |
|
2507 |
index = self.two_graph_index(catch_adds=True) |
|
2508 |
index.add_versions([ |
|
2670.2.2
by Robert Collins
* In ``bzrlib.knit`` the internal interface has been altered to use |
2509 |
('new', 'fulltext,no-eol', (None, 50, 60), []), |
2510 |
('new2', 'fulltext', (None, 0, 6), []), |
|
2625.8.1
by Robert Collins
LIBRARY API BREAKS: |
2511 |
])
|
2624.2.5
by Robert Collins
Change bzrlib.index.Index keys to be 1-tuples, not strings. |
2512 |
self.assertEqual([(('new', ), 'N50 60'), (('new2', ), ' 0 6')], |
2625.8.1
by Robert Collins
LIBRARY API BREAKS: |
2513 |
sorted(self.caught_entries[0])) |
2514 |
self.assertEqual(1, len(self.caught_entries)) |
|
2515 |
||
2516 |
def test_add_versions_delta_not_delta_index(self): |
|
2517 |
index = self.two_graph_index(catch_adds=True) |
|
2518 |
self.assertRaises(errors.KnitCorrupt, index.add_versions, |
|
2670.2.2
by Robert Collins
* In ``bzrlib.knit`` the internal interface has been altered to use |
2519 |
[('new', 'no-eol,line-delta', (None, 0, 100), ['parent'])]) |
2625.8.1
by Robert Collins
LIBRARY API BREAKS: |
2520 |
self.assertEqual([], self.caught_entries) |
2521 |
||
2522 |
def test_add_versions_parents_not_parents_index(self): |
|
2523 |
index = self.two_graph_index(catch_adds=True) |
|
2524 |
self.assertRaises(errors.KnitCorrupt, index.add_versions, |
|
2670.2.2
by Robert Collins
* In ``bzrlib.knit`` the internal interface has been altered to use |
2525 |
[('new', 'no-eol,fulltext', (None, 0, 100), ['parent'])]) |
2625.8.1
by Robert Collins
LIBRARY API BREAKS: |
2526 |
self.assertEqual([], self.caught_entries) |
2527 |
||
2528 |
def test_add_versions_same_dup(self): |
|
2529 |
index = self.two_graph_index(catch_adds=True) |
|
2530 |
# options can be spelt two different ways
|
|
2670.2.2
by Robert Collins
* In ``bzrlib.knit`` the internal interface has been altered to use |
2531 |
index.add_versions([('tip', 'fulltext,no-eol', (None, 0, 100), [])]) |
2532 |
index.add_versions([('tip', 'no-eol,fulltext', (None, 0, 100), [])]) |
|
2625.8.1
by Robert Collins
LIBRARY API BREAKS: |
2533 |
# but neither should have added data.
|
2534 |
self.assertEqual([[], []], self.caught_entries) |
|
2535 |
||
2536 |
def test_add_versions_different_dup(self): |
|
2537 |
index = self.two_graph_index(catch_adds=True) |
|
2538 |
# change options
|
|
2539 |
self.assertRaises(errors.KnitCorrupt, index.add_versions, |
|
2670.2.2
by Robert Collins
* In ``bzrlib.knit`` the internal interface has been altered to use |
2540 |
[('tip', 'no-eol,line-delta', (None, 0, 100), [])]) |
2541 |
self.assertRaises(errors.KnitCorrupt, index.add_versions, |
|
2542 |
[('tip', 'line-delta,no-eol', (None, 0, 100), [])]) |
|
2543 |
self.assertRaises(errors.KnitCorrupt, index.add_versions, |
|
2544 |
[('tip', 'fulltext', (None, 0, 100), [])]) |
|
2625.8.1
by Robert Collins
LIBRARY API BREAKS: |
2545 |
# position/length
|
2546 |
self.assertRaises(errors.KnitCorrupt, index.add_versions, |
|
2670.2.2
by Robert Collins
* In ``bzrlib.knit`` the internal interface has been altered to use |
2547 |
[('tip', 'fulltext,no-eol', (None, 50, 100), [])]) |
2625.8.1
by Robert Collins
LIBRARY API BREAKS: |
2548 |
self.assertRaises(errors.KnitCorrupt, index.add_versions, |
2670.2.2
by Robert Collins
* In ``bzrlib.knit`` the internal interface has been altered to use |
2549 |
[('tip', 'fulltext,no-eol', (None, 0, 1000), [])]) |
2625.8.1
by Robert Collins
LIBRARY API BREAKS: |
2550 |
# parents
|
2551 |
self.assertRaises(errors.KnitCorrupt, index.add_versions, |
|
2670.2.2
by Robert Collins
* In ``bzrlib.knit`` the internal interface has been altered to use |
2552 |
[('tip', 'fulltext,no-eol', (None, 0, 100), ['parent'])]) |
2625.8.1
by Robert Collins
LIBRARY API BREAKS: |
2553 |
# change options in the second record
|
2554 |
self.assertRaises(errors.KnitCorrupt, index.add_versions, |
|
2670.2.2
by Robert Collins
* In ``bzrlib.knit`` the internal interface has been altered to use |
2555 |
[('tip', 'fulltext,no-eol', (None, 0, 100), []), |
2556 |
('tip', 'no-eol,line-delta', (None, 0, 100), [])]) |
|
2625.8.1
by Robert Collins
LIBRARY API BREAKS: |
2557 |
self.assertEqual([], self.caught_entries) |
2558 |
||
2559 |
def test_iter_parents(self): |
|
2560 |
index = self.two_graph_index() |
|
2561 |
self.assertEqual(set([ |
|
2562 |
('tip', ()), ('tail', ()), ('parent', ()), ('separate', ()) |
|
2563 |
]),
|
|
2564 |
set(index.iter_parents(['tip', 'tail', 'ghost', 'parent', 'separate']))) |
|
2565 |
self.assertEqual(set([('tip', ())]), |
|
2566 |
set(index.iter_parents(['tip']))) |
|
2567 |
self.assertEqual(set(), |
|
2568 |
set(index.iter_parents([]))) |