##// END OF EJS Templates
test-revlog-raw: drop the overwrite of dead code...
marmoute -
r50568:e3377629 default
parent child Browse files
Show More
@@ -1,528 +1,524 b''
1 # test revlog interaction about raw data (flagprocessor)
1 # test revlog interaction about raw data (flagprocessor)
2
2
3
3
4 import collections
4 import collections
5 import hashlib
5 import hashlib
6 import sys
6 import sys
7
7
8 from mercurial import (
8 from mercurial import (
9 encoding,
9 encoding,
10 revlog,
10 revlog,
11 transaction,
11 transaction,
12 vfs,
12 vfs,
13 )
13 )
14
14
15 from mercurial.revlogutils import (
15 from mercurial.revlogutils import (
16 constants,
16 constants,
17 deltas,
17 deltas,
18 flagutil,
18 flagutil,
19 )
19 )
20
20
21
21
22 class _NoTransaction:
22 class _NoTransaction:
23 """transaction like object to update the nodemap outside a transaction"""
23 """transaction like object to update the nodemap outside a transaction"""
24
24
25 def __init__(self):
25 def __init__(self):
26 self._postclose = {}
26 self._postclose = {}
27
27
28 def addpostclose(self, callback_id, callback_func):
28 def addpostclose(self, callback_id, callback_func):
29 self._postclose[callback_id] = callback_func
29 self._postclose[callback_id] = callback_func
30
30
31 def registertmp(self, *args, **kwargs):
31 def registertmp(self, *args, **kwargs):
32 pass
32 pass
33
33
34 def addbackup(self, *args, **kwargs):
34 def addbackup(self, *args, **kwargs):
35 pass
35 pass
36
36
37 def add(self, *args, **kwargs):
37 def add(self, *args, **kwargs):
38 pass
38 pass
39
39
40 def addabort(self, *args, **kwargs):
40 def addabort(self, *args, **kwargs):
41 pass
41 pass
42
42
43 def _report(self, *args):
43 def _report(self, *args):
44 pass
44 pass
45
45
46
46
47 # TESTTMP is optional. This makes it convenient to run without run-tests.py
47 # TESTTMP is optional. This makes it convenient to run without run-tests.py
48 tvfs = vfs.vfs(encoding.environ.get(b'TESTTMP', b'/tmp'))
48 tvfs = vfs.vfs(encoding.environ.get(b'TESTTMP', b'/tmp'))
49
49
50 # Enable generaldelta otherwise revlog won't use delta as expected by the test
50 # Enable generaldelta otherwise revlog won't use delta as expected by the test
51 tvfs.options = {
51 tvfs.options = {
52 b'generaldelta': True,
52 b'generaldelta': True,
53 b'revlogv1': True,
53 b'revlogv1': True,
54 b'sparse-revlog': True,
54 b'sparse-revlog': True,
55 }
55 }
56
56
57 # The test wants to control whether to use delta explicitly, based on
58 # "storedeltachains".
59 revlog.revlog._isgooddeltainfo = lambda self, d, textlen: self._storedeltachains
60
61
57
62 def abort(msg):
58 def abort(msg):
63 print('abort: %s' % msg)
59 print('abort: %s' % msg)
64 # Return 0 so run-tests.py could compare the output.
60 # Return 0 so run-tests.py could compare the output.
65 sys.exit()
61 sys.exit()
66
62
67
63
68 # Register a revlog processor for flag EXTSTORED.
64 # Register a revlog processor for flag EXTSTORED.
69 #
65 #
70 # It simply prepends a fixed header, and replaces '1' to 'i'. So it has
66 # It simply prepends a fixed header, and replaces '1' to 'i'. So it has
71 # insertion and replacement, and may be interesting to test revlog's line-based
67 # insertion and replacement, and may be interesting to test revlog's line-based
72 # deltas.
68 # deltas.
73 _extheader = b'E\n'
69 _extheader = b'E\n'
74
70
75
71
76 def readprocessor(self, rawtext):
72 def readprocessor(self, rawtext):
77 # True: the returned text could be used to verify hash
73 # True: the returned text could be used to verify hash
78 text = rawtext[len(_extheader) :].replace(b'i', b'1')
74 text = rawtext[len(_extheader) :].replace(b'i', b'1')
79 return text, True
75 return text, True
80
76
81
77
82 def writeprocessor(self, text):
78 def writeprocessor(self, text):
83 # False: the returned rawtext shouldn't be used to verify hash
79 # False: the returned rawtext shouldn't be used to verify hash
84 rawtext = _extheader + text.replace(b'1', b'i')
80 rawtext = _extheader + text.replace(b'1', b'i')
85 return rawtext, False
81 return rawtext, False
86
82
87
83
88 def rawprocessor(self, rawtext):
84 def rawprocessor(self, rawtext):
89 # False: do not verify hash. Only the content returned by "readprocessor"
85 # False: do not verify hash. Only the content returned by "readprocessor"
90 # can be used to verify hash.
86 # can be used to verify hash.
91 return False
87 return False
92
88
93
89
94 flagutil.addflagprocessor(
90 flagutil.addflagprocessor(
95 revlog.REVIDX_EXTSTORED, (readprocessor, writeprocessor, rawprocessor)
91 revlog.REVIDX_EXTSTORED, (readprocessor, writeprocessor, rawprocessor)
96 )
92 )
97
93
98 # Utilities about reading and appending revlog
94 # Utilities about reading and appending revlog
99
95
100
96
101 def newtransaction():
97 def newtransaction():
102 # A transaction is required to write revlogs
98 # A transaction is required to write revlogs
103 report = lambda msg: None
99 report = lambda msg: None
104 return transaction.transaction(report, tvfs, {'plain': tvfs}, b'journal')
100 return transaction.transaction(report, tvfs, {'plain': tvfs}, b'journal')
105
101
106
102
107 def newrevlog(name=b'_testrevlog', recreate=False):
103 def newrevlog(name=b'_testrevlog', recreate=False):
108 if recreate:
104 if recreate:
109 tvfs.tryunlink(name + b'.i')
105 tvfs.tryunlink(name + b'.i')
110 target = (constants.KIND_OTHER, b'test')
106 target = (constants.KIND_OTHER, b'test')
111 rlog = revlog.revlog(tvfs, target=target, radix=name)
107 rlog = revlog.revlog(tvfs, target=target, radix=name)
112 return rlog
108 return rlog
113
109
114
110
115 def appendrev(rlog, text, tr, isext=False, isdelta=True):
111 def appendrev(rlog, text, tr, isext=False, isdelta=True):
116 """Append a revision. If isext is True, set the EXTSTORED flag so flag
112 """Append a revision. If isext is True, set the EXTSTORED flag so flag
117 processor will be used (and rawtext is different from text). If isdelta is
113 processor will be used (and rawtext is different from text). If isdelta is
118 True, force the revision to be a delta, otherwise it's full text.
114 True, force the revision to be a delta, otherwise it's full text.
119 """
115 """
120 nextrev = len(rlog)
116 nextrev = len(rlog)
121 p1 = rlog.node(nextrev - 1)
117 p1 = rlog.node(nextrev - 1)
122 p2 = rlog.nullid
118 p2 = rlog.nullid
123 if isext:
119 if isext:
124 flags = revlog.REVIDX_EXTSTORED
120 flags = revlog.REVIDX_EXTSTORED
125 else:
121 else:
126 flags = revlog.REVIDX_DEFAULT_FLAGS
122 flags = revlog.REVIDX_DEFAULT_FLAGS
127 # Change storedeltachains temporarily, to override revlog's delta decision
123 # Change storedeltachains temporarily, to override revlog's delta decision
128 rlog._storedeltachains = isdelta
124 rlog._storedeltachains = isdelta
129 try:
125 try:
130 rlog.addrevision(text, tr, nextrev, p1, p2, flags=flags)
126 rlog.addrevision(text, tr, nextrev, p1, p2, flags=flags)
131 return nextrev
127 return nextrev
132 except Exception as ex:
128 except Exception as ex:
133 abort('rev %d: failed to append: %s' % (nextrev, ex))
129 abort('rev %d: failed to append: %s' % (nextrev, ex))
134 finally:
130 finally:
135 # Restore storedeltachains. It is always True, see revlog.__init__
131 # Restore storedeltachains. It is always True, see revlog.__init__
136 rlog._storedeltachains = True
132 rlog._storedeltachains = True
137
133
138
134
139 def addgroupcopy(rlog, tr, destname=b'_destrevlog', optimaldelta=True):
135 def addgroupcopy(rlog, tr, destname=b'_destrevlog', optimaldelta=True):
140 """Copy revlog to destname using revlog.addgroup. Return the copied revlog.
136 """Copy revlog to destname using revlog.addgroup. Return the copied revlog.
141
137
142 This emulates push or pull. They use changegroup. Changegroup requires
138 This emulates push or pull. They use changegroup. Changegroup requires
143 repo to work. We don't have a repo, so a dummy changegroup is used.
139 repo to work. We don't have a repo, so a dummy changegroup is used.
144
140
145 If optimaldelta is True, use optimized delta parent, so the destination
141 If optimaldelta is True, use optimized delta parent, so the destination
146 revlog could probably reuse it. Otherwise it builds sub-optimal delta, and
142 revlog could probably reuse it. Otherwise it builds sub-optimal delta, and
147 the destination revlog needs more work to use it.
143 the destination revlog needs more work to use it.
148
144
149 This exercises some revlog.addgroup (and revlog._addrevision(text=None))
145 This exercises some revlog.addgroup (and revlog._addrevision(text=None))
150 code path, which is not covered by "appendrev" alone.
146 code path, which is not covered by "appendrev" alone.
151 """
147 """
152
148
153 class dummychangegroup:
149 class dummychangegroup:
154 @staticmethod
150 @staticmethod
155 def deltachunk(pnode):
151 def deltachunk(pnode):
156 pnode = pnode or rlog.nullid
152 pnode = pnode or rlog.nullid
157 parentrev = rlog.rev(pnode)
153 parentrev = rlog.rev(pnode)
158 r = parentrev + 1
154 r = parentrev + 1
159 if r >= len(rlog):
155 if r >= len(rlog):
160 return {}
156 return {}
161 if optimaldelta:
157 if optimaldelta:
162 deltaparent = parentrev
158 deltaparent = parentrev
163 else:
159 else:
164 # suboptimal deltaparent
160 # suboptimal deltaparent
165 deltaparent = min(0, parentrev)
161 deltaparent = min(0, parentrev)
166 if not rlog.candelta(deltaparent, r):
162 if not rlog.candelta(deltaparent, r):
167 deltaparent = -1
163 deltaparent = -1
168 return {
164 return {
169 b'node': rlog.node(r),
165 b'node': rlog.node(r),
170 b'p1': pnode,
166 b'p1': pnode,
171 b'p2': rlog.nullid,
167 b'p2': rlog.nullid,
172 b'cs': rlog.node(rlog.linkrev(r)),
168 b'cs': rlog.node(rlog.linkrev(r)),
173 b'flags': rlog.flags(r),
169 b'flags': rlog.flags(r),
174 b'deltabase': rlog.node(deltaparent),
170 b'deltabase': rlog.node(deltaparent),
175 b'delta': rlog.revdiff(deltaparent, r),
171 b'delta': rlog.revdiff(deltaparent, r),
176 b'sidedata': rlog.sidedata(r),
172 b'sidedata': rlog.sidedata(r),
177 }
173 }
178
174
179 def deltaiter(self):
175 def deltaiter(self):
180 chain = None
176 chain = None
181 for chunkdata in iter(lambda: self.deltachunk(chain), {}):
177 for chunkdata in iter(lambda: self.deltachunk(chain), {}):
182 node = chunkdata[b'node']
178 node = chunkdata[b'node']
183 p1 = chunkdata[b'p1']
179 p1 = chunkdata[b'p1']
184 p2 = chunkdata[b'p2']
180 p2 = chunkdata[b'p2']
185 cs = chunkdata[b'cs']
181 cs = chunkdata[b'cs']
186 deltabase = chunkdata[b'deltabase']
182 deltabase = chunkdata[b'deltabase']
187 delta = chunkdata[b'delta']
183 delta = chunkdata[b'delta']
188 flags = chunkdata[b'flags']
184 flags = chunkdata[b'flags']
189 sidedata = chunkdata[b'sidedata']
185 sidedata = chunkdata[b'sidedata']
190
186
191 chain = node
187 chain = node
192
188
193 yield (node, p1, p2, cs, deltabase, delta, flags, sidedata)
189 yield (node, p1, p2, cs, deltabase, delta, flags, sidedata)
194
190
195 def linkmap(lnode):
191 def linkmap(lnode):
196 return rlog.rev(lnode)
192 return rlog.rev(lnode)
197
193
198 dlog = newrevlog(destname, recreate=True)
194 dlog = newrevlog(destname, recreate=True)
199 dummydeltas = dummychangegroup().deltaiter()
195 dummydeltas = dummychangegroup().deltaiter()
200 dlog.addgroup(dummydeltas, linkmap, tr)
196 dlog.addgroup(dummydeltas, linkmap, tr)
201 return dlog
197 return dlog
202
198
203
199
204 def lowlevelcopy(rlog, tr, destname=b'_destrevlog'):
200 def lowlevelcopy(rlog, tr, destname=b'_destrevlog'):
205 """Like addgroupcopy, but use the low level revlog._addrevision directly.
201 """Like addgroupcopy, but use the low level revlog._addrevision directly.
206
202
207 It exercises some code paths that are hard to reach easily otherwise.
203 It exercises some code paths that are hard to reach easily otherwise.
208 """
204 """
209 dlog = newrevlog(destname, recreate=True)
205 dlog = newrevlog(destname, recreate=True)
210 for r in rlog:
206 for r in rlog:
211 p1 = rlog.node(r - 1)
207 p1 = rlog.node(r - 1)
212 p2 = rlog.nullid
208 p2 = rlog.nullid
213 if r == 0 or (rlog.flags(r) & revlog.REVIDX_EXTSTORED):
209 if r == 0 or (rlog.flags(r) & revlog.REVIDX_EXTSTORED):
214 text = rlog.rawdata(r)
210 text = rlog.rawdata(r)
215 cachedelta = None
211 cachedelta = None
216 else:
212 else:
217 # deltaparent cannot have EXTSTORED flag.
213 # deltaparent cannot have EXTSTORED flag.
218 deltaparent = max(
214 deltaparent = max(
219 [-1]
215 [-1]
220 + [
216 + [
221 p
217 p
222 for p in range(r)
218 for p in range(r)
223 if rlog.flags(p) & revlog.REVIDX_EXTSTORED == 0
219 if rlog.flags(p) & revlog.REVIDX_EXTSTORED == 0
224 ]
220 ]
225 )
221 )
226 text = None
222 text = None
227 cachedelta = (deltaparent, rlog.revdiff(deltaparent, r))
223 cachedelta = (deltaparent, rlog.revdiff(deltaparent, r))
228 flags = rlog.flags(r)
224 flags = rlog.flags(r)
229 with dlog._writing(_NoTransaction()):
225 with dlog._writing(_NoTransaction()):
230 dlog._addrevision(
226 dlog._addrevision(
231 rlog.node(r),
227 rlog.node(r),
232 text,
228 text,
233 tr,
229 tr,
234 r,
230 r,
235 p1,
231 p1,
236 p2,
232 p2,
237 flags,
233 flags,
238 cachedelta,
234 cachedelta,
239 )
235 )
240 return dlog
236 return dlog
241
237
242
238
243 # Utilities to generate revisions for testing
239 # Utilities to generate revisions for testing
244
240
245
241
246 def genbits(n):
242 def genbits(n):
247 """Given a number n, generate (2 ** (n * 2) + 1) numbers in range(2 ** n).
243 """Given a number n, generate (2 ** (n * 2) + 1) numbers in range(2 ** n).
248 i.e. the generated numbers have a width of n bits.
244 i.e. the generated numbers have a width of n bits.
249
245
250 The combination of two adjacent numbers will cover all possible cases.
246 The combination of two adjacent numbers will cover all possible cases.
251 That is to say, given any x, y where both x, and y are in range(2 ** n),
247 That is to say, given any x, y where both x, and y are in range(2 ** n),
252 there is an x followed immediately by y in the generated sequence.
248 there is an x followed immediately by y in the generated sequence.
253 """
249 """
254 m = 2 ** n
250 m = 2 ** n
255
251
256 # Gray Code. See https://en.wikipedia.org/wiki/Gray_code
252 # Gray Code. See https://en.wikipedia.org/wiki/Gray_code
257 gray = lambda x: x ^ (x >> 1)
253 gray = lambda x: x ^ (x >> 1)
258 reversegray = {gray(i): i for i in range(m)}
254 reversegray = {gray(i): i for i in range(m)}
259
255
260 # Generate (n * 2) bit gray code, yield lower n bits as X, and look for
256 # Generate (n * 2) bit gray code, yield lower n bits as X, and look for
261 # the next unused gray code where higher n bits equal to X.
257 # the next unused gray code where higher n bits equal to X.
262
258
263 # For gray codes whose higher bits are X, a[X] of them have been used.
259 # For gray codes whose higher bits are X, a[X] of them have been used.
264 a = [0] * m
260 a = [0] * m
265
261
266 # Iterate from 0.
262 # Iterate from 0.
267 x = 0
263 x = 0
268 yield x
264 yield x
269 for i in range(m * m):
265 for i in range(m * m):
270 x = reversegray[x]
266 x = reversegray[x]
271 y = gray(a[x] + x * m) & (m - 1)
267 y = gray(a[x] + x * m) & (m - 1)
272 assert a[x] < m
268 assert a[x] < m
273 a[x] += 1
269 a[x] += 1
274 x = y
270 x = y
275 yield x
271 yield x
276
272
277
273
278 def gentext(rev):
274 def gentext(rev):
279 '''Given a revision number, generate dummy text'''
275 '''Given a revision number, generate dummy text'''
280 return b''.join(b'%d\n' % j for j in range(-1, rev % 5))
276 return b''.join(b'%d\n' % j for j in range(-1, rev % 5))
281
277
282
278
283 def writecases(rlog, tr):
279 def writecases(rlog, tr):
284 """Write some revisions interested to the test.
280 """Write some revisions interested to the test.
285
281
286 The test is interested in 3 properties of a revision:
282 The test is interested in 3 properties of a revision:
287
283
288 - Is it a delta or a full text? (isdelta)
284 - Is it a delta or a full text? (isdelta)
289 This is to catch some delta application issues.
285 This is to catch some delta application issues.
290 - Does it have a flag of EXTSTORED? (isext)
286 - Does it have a flag of EXTSTORED? (isext)
291 This is to catch some flag processor issues. Especially when
287 This is to catch some flag processor issues. Especially when
292 interacted with revlog deltas.
288 interacted with revlog deltas.
293 - Is its text empty? (isempty)
289 - Is its text empty? (isempty)
294 This is less important. It is intended to try to catch some careless
290 This is less important. It is intended to try to catch some careless
295 checks like "if text" instead of "if text is None". Note: if flag
291 checks like "if text" instead of "if text is None". Note: if flag
296 processor is involved, raw text may be not empty.
292 processor is involved, raw text may be not empty.
297
293
298 Write 65 revisions. So that all combinations of the above flags for
294 Write 65 revisions. So that all combinations of the above flags for
299 adjacent revisions are covered. That is to say,
295 adjacent revisions are covered. That is to say,
300
296
301 len(set(
297 len(set(
302 (r.delta, r.ext, r.empty, (r+1).delta, (r+1).ext, (r+1).empty)
298 (r.delta, r.ext, r.empty, (r+1).delta, (r+1).ext, (r+1).empty)
303 for r in range(len(rlog) - 1)
299 for r in range(len(rlog) - 1)
304 )) is 64.
300 )) is 64.
305
301
306 Where "r.delta", "r.ext", and "r.empty" are booleans matching properties
302 Where "r.delta", "r.ext", and "r.empty" are booleans matching properties
307 mentioned above.
303 mentioned above.
308
304
309 Return expected [(text, rawtext)].
305 Return expected [(text, rawtext)].
310 """
306 """
311 result = []
307 result = []
312 for i, x in enumerate(genbits(3)):
308 for i, x in enumerate(genbits(3)):
313 isdelta, isext, isempty = bool(x & 1), bool(x & 2), bool(x & 4)
309 isdelta, isext, isempty = bool(x & 1), bool(x & 2), bool(x & 4)
314 if isempty:
310 if isempty:
315 text = b''
311 text = b''
316 else:
312 else:
317 text = gentext(i)
313 text = gentext(i)
318 rev = appendrev(rlog, text, tr, isext=isext, isdelta=isdelta)
314 rev = appendrev(rlog, text, tr, isext=isext, isdelta=isdelta)
319
315
320 # Verify text, rawtext, and rawsize
316 # Verify text, rawtext, and rawsize
321 if isext:
317 if isext:
322 rawtext = writeprocessor(None, text)[0]
318 rawtext = writeprocessor(None, text)[0]
323 else:
319 else:
324 rawtext = text
320 rawtext = text
325 if rlog.rawsize(rev) != len(rawtext):
321 if rlog.rawsize(rev) != len(rawtext):
326 abort('rev %d: wrong rawsize' % rev)
322 abort('rev %d: wrong rawsize' % rev)
327 if rlog.revision(rev) != text:
323 if rlog.revision(rev) != text:
328 abort('rev %d: wrong text' % rev)
324 abort('rev %d: wrong text' % rev)
329 if rlog.rawdata(rev) != rawtext:
325 if rlog.rawdata(rev) != rawtext:
330 abort('rev %d: wrong rawtext' % rev)
326 abort('rev %d: wrong rawtext' % rev)
331 result.append((text, rawtext))
327 result.append((text, rawtext))
332
328
333 # Verify flags like isdelta, isext work as expected
329 # Verify flags like isdelta, isext work as expected
334 # isdelta can be overridden to False if this or p1 has isext set
330 # isdelta can be overridden to False if this or p1 has isext set
335 if bool(rlog.deltaparent(rev) > -1) and not isdelta:
331 if bool(rlog.deltaparent(rev) > -1) and not isdelta:
336 abort('rev %d: isdelta is unexpected' % rev)
332 abort('rev %d: isdelta is unexpected' % rev)
337 if bool(rlog.flags(rev)) != isext:
333 if bool(rlog.flags(rev)) != isext:
338 abort('rev %d: isext is ineffective' % rev)
334 abort('rev %d: isext is ineffective' % rev)
339 return result
335 return result
340
336
341
337
342 # Main test and checking
338 # Main test and checking
343
339
344
340
345 def checkrevlog(rlog, expected):
341 def checkrevlog(rlog, expected):
346 '''Check if revlog has expected contents. expected is [(text, rawtext)]'''
342 '''Check if revlog has expected contents. expected is [(text, rawtext)]'''
347 # Test using different access orders. This could expose some issues
343 # Test using different access orders. This could expose some issues
348 # depending on revlog caching (see revlog._cache).
344 # depending on revlog caching (see revlog._cache).
349 for r0 in range(len(rlog) - 1):
345 for r0 in range(len(rlog) - 1):
350 r1 = r0 + 1
346 r1 = r0 + 1
351 for revorder in [[r0, r1], [r1, r0]]:
347 for revorder in [[r0, r1], [r1, r0]]:
352 for raworder in [[True], [False], [True, False], [False, True]]:
348 for raworder in [[True], [False], [True, False], [False, True]]:
353 nlog = newrevlog()
349 nlog = newrevlog()
354 for rev in revorder:
350 for rev in revorder:
355 for raw in raworder:
351 for raw in raworder:
356 if raw:
352 if raw:
357 t = nlog.rawdata(rev)
353 t = nlog.rawdata(rev)
358 else:
354 else:
359 t = nlog.revision(rev)
355 t = nlog.revision(rev)
360 if t != expected[rev][int(raw)]:
356 if t != expected[rev][int(raw)]:
361 abort(
357 abort(
362 'rev %d: corrupted %stext'
358 'rev %d: corrupted %stext'
363 % (rev, raw and 'raw' or '')
359 % (rev, raw and 'raw' or '')
364 )
360 )
365
361
366
362
367 slicingdata = [
363 slicingdata = [
368 ([0, 1, 2, 3, 55, 56, 58, 59, 60], [[0, 1], [2], [58], [59, 60]], 10),
364 ([0, 1, 2, 3, 55, 56, 58, 59, 60], [[0, 1], [2], [58], [59, 60]], 10),
369 ([0, 1, 2, 3, 55, 56, 58, 59, 60], [[0, 1], [2], [58], [59, 60]], 10),
365 ([0, 1, 2, 3, 55, 56, 58, 59, 60], [[0, 1], [2], [58], [59, 60]], 10),
370 (
366 (
371 [-1, 0, 1, 2, 3, 55, 56, 58, 59, 60],
367 [-1, 0, 1, 2, 3, 55, 56, 58, 59, 60],
372 [[-1, 0, 1], [2], [58], [59, 60]],
368 [[-1, 0, 1], [2], [58], [59, 60]],
373 10,
369 10,
374 ),
370 ),
375 ]
371 ]
376
372
377
373
378 def slicingtest(rlog):
374 def slicingtest(rlog):
379 oldmin = rlog._srmingapsize
375 oldmin = rlog._srmingapsize
380 try:
376 try:
381 # the test revlog is small, we remove the floor under which we
377 # the test revlog is small, we remove the floor under which we
382 # slicing is diregarded.
378 # slicing is diregarded.
383 rlog._srmingapsize = 0
379 rlog._srmingapsize = 0
384 for item in slicingdata:
380 for item in slicingdata:
385 chain, expected, target = item
381 chain, expected, target = item
386 result = deltas.slicechunk(rlog, chain, targetsize=target)
382 result = deltas.slicechunk(rlog, chain, targetsize=target)
387 result = list(result)
383 result = list(result)
388 if result != expected:
384 if result != expected:
389 print('slicing differ:')
385 print('slicing differ:')
390 print(' chain: %s' % chain)
386 print(' chain: %s' % chain)
391 print(' target: %s' % target)
387 print(' target: %s' % target)
392 print(' expected: %s' % expected)
388 print(' expected: %s' % expected)
393 print(' result: %s' % result)
389 print(' result: %s' % result)
394 finally:
390 finally:
395 rlog._srmingapsize = oldmin
391 rlog._srmingapsize = oldmin
396
392
397
393
398 def md5sum(s):
394 def md5sum(s):
399 return hashlib.md5(s).digest()
395 return hashlib.md5(s).digest()
400
396
401
397
402 def _maketext(*coord):
398 def _maketext(*coord):
403 """create piece of text according to range of integers
399 """create piece of text according to range of integers
404
400
405 The test returned use a md5sum of the integer to make it less
401 The test returned use a md5sum of the integer to make it less
406 compressible"""
402 compressible"""
407 pieces = []
403 pieces = []
408 for start, size in coord:
404 for start, size in coord:
409 num = range(start, start + size)
405 num = range(start, start + size)
410 p = [md5sum(b'%d' % r) for r in num]
406 p = [md5sum(b'%d' % r) for r in num]
411 pieces.append(b'\n'.join(p))
407 pieces.append(b'\n'.join(p))
412 return b'\n'.join(pieces) + b'\n'
408 return b'\n'.join(pieces) + b'\n'
413
409
414
410
415 data = [
411 data = [
416 _maketext((0, 120), (456, 60)),
412 _maketext((0, 120), (456, 60)),
417 _maketext((0, 120), (345, 60)),
413 _maketext((0, 120), (345, 60)),
418 _maketext((0, 120), (734, 60)),
414 _maketext((0, 120), (734, 60)),
419 _maketext((0, 120), (734, 60), (923, 45)),
415 _maketext((0, 120), (734, 60), (923, 45)),
420 _maketext((0, 120), (734, 60), (234, 45)),
416 _maketext((0, 120), (734, 60), (234, 45)),
421 _maketext((0, 120), (734, 60), (564, 45)),
417 _maketext((0, 120), (734, 60), (564, 45)),
422 _maketext((0, 120), (734, 60), (361, 45)),
418 _maketext((0, 120), (734, 60), (361, 45)),
423 _maketext((0, 120), (734, 60), (489, 45)),
419 _maketext((0, 120), (734, 60), (489, 45)),
424 _maketext((0, 120), (123, 60)),
420 _maketext((0, 120), (123, 60)),
425 _maketext((0, 120), (145, 60)),
421 _maketext((0, 120), (145, 60)),
426 _maketext((0, 120), (104, 60)),
422 _maketext((0, 120), (104, 60)),
427 _maketext((0, 120), (430, 60)),
423 _maketext((0, 120), (430, 60)),
428 _maketext((0, 120), (430, 60), (923, 45)),
424 _maketext((0, 120), (430, 60), (923, 45)),
429 _maketext((0, 120), (430, 60), (234, 45)),
425 _maketext((0, 120), (430, 60), (234, 45)),
430 _maketext((0, 120), (430, 60), (564, 45)),
426 _maketext((0, 120), (430, 60), (564, 45)),
431 _maketext((0, 120), (430, 60), (361, 45)),
427 _maketext((0, 120), (430, 60), (361, 45)),
432 _maketext((0, 120), (430, 60), (489, 45)),
428 _maketext((0, 120), (430, 60), (489, 45)),
433 _maketext((0, 120), (249, 60)),
429 _maketext((0, 120), (249, 60)),
434 _maketext((0, 120), (832, 60)),
430 _maketext((0, 120), (832, 60)),
435 _maketext((0, 120), (891, 60)),
431 _maketext((0, 120), (891, 60)),
436 _maketext((0, 120), (543, 60)),
432 _maketext((0, 120), (543, 60)),
437 _maketext((0, 120), (120, 60)),
433 _maketext((0, 120), (120, 60)),
438 _maketext((0, 120), (60, 60), (768, 30)),
434 _maketext((0, 120), (60, 60), (768, 30)),
439 _maketext((0, 120), (60, 60), (260, 30)),
435 _maketext((0, 120), (60, 60), (260, 30)),
440 _maketext((0, 120), (60, 60), (450, 30)),
436 _maketext((0, 120), (60, 60), (450, 30)),
441 _maketext((0, 120), (60, 60), (361, 30)),
437 _maketext((0, 120), (60, 60), (361, 30)),
442 _maketext((0, 120), (60, 60), (886, 30)),
438 _maketext((0, 120), (60, 60), (886, 30)),
443 _maketext((0, 120), (60, 60), (116, 30)),
439 _maketext((0, 120), (60, 60), (116, 30)),
444 _maketext((0, 120), (60, 60), (567, 30), (629, 40)),
440 _maketext((0, 120), (60, 60), (567, 30), (629, 40)),
445 _maketext((0, 120), (60, 60), (569, 30), (745, 40)),
441 _maketext((0, 120), (60, 60), (569, 30), (745, 40)),
446 _maketext((0, 120), (60, 60), (777, 30), (700, 40)),
442 _maketext((0, 120), (60, 60), (777, 30), (700, 40)),
447 _maketext((0, 120), (60, 60), (618, 30), (398, 40), (158, 10)),
443 _maketext((0, 120), (60, 60), (618, 30), (398, 40), (158, 10)),
448 ]
444 ]
449
445
450
446
451 def makesnapshot(tr):
447 def makesnapshot(tr):
452 rl = newrevlog(name=b'_snaprevlog3', recreate=True)
448 rl = newrevlog(name=b'_snaprevlog3', recreate=True)
453 for i in data:
449 for i in data:
454 appendrev(rl, i, tr)
450 appendrev(rl, i, tr)
455 return rl
451 return rl
456
452
457
453
458 snapshots = [-1, 0, 6, 8, 11, 17, 19, 21, 25, 30]
454 snapshots = [-1, 0, 6, 8, 11, 17, 19, 21, 25, 30]
459
455
460
456
461 def issnapshottest(rlog):
457 def issnapshottest(rlog):
462 result = []
458 result = []
463 if rlog.issnapshot(-1):
459 if rlog.issnapshot(-1):
464 result.append(-1)
460 result.append(-1)
465 for rev in rlog:
461 for rev in rlog:
466 if rlog.issnapshot(rev):
462 if rlog.issnapshot(rev):
467 result.append(rev)
463 result.append(rev)
468 if snapshots != result:
464 if snapshots != result:
469 print('snapshot differ:')
465 print('snapshot differ:')
470 print(' expected: %s' % snapshots)
466 print(' expected: %s' % snapshots)
471 print(' got: %s' % result)
467 print(' got: %s' % result)
472
468
473
469
474 snapshotmapall = {0: [6, 8, 11, 17, 19, 25], 8: [21], -1: [0, 30]}
470 snapshotmapall = {0: [6, 8, 11, 17, 19, 25], 8: [21], -1: [0, 30]}
475 snapshotmap15 = {0: [17, 19, 25], 8: [21], -1: [30]}
471 snapshotmap15 = {0: [17, 19, 25], 8: [21], -1: [30]}
476
472
477
473
478 def findsnapshottest(rlog):
474 def findsnapshottest(rlog):
479 resultall = collections.defaultdict(list)
475 resultall = collections.defaultdict(list)
480 deltas._findsnapshots(rlog, resultall, 0)
476 deltas._findsnapshots(rlog, resultall, 0)
481 resultall = dict(resultall.items())
477 resultall = dict(resultall.items())
482 if resultall != snapshotmapall:
478 if resultall != snapshotmapall:
483 print('snapshot map differ:')
479 print('snapshot map differ:')
484 print(' expected: %s' % snapshotmapall)
480 print(' expected: %s' % snapshotmapall)
485 print(' got: %s' % resultall)
481 print(' got: %s' % resultall)
486 result15 = collections.defaultdict(list)
482 result15 = collections.defaultdict(list)
487 deltas._findsnapshots(rlog, result15, 15)
483 deltas._findsnapshots(rlog, result15, 15)
488 result15 = dict(result15.items())
484 result15 = dict(result15.items())
489 if result15 != snapshotmap15:
485 if result15 != snapshotmap15:
490 print('snapshot map differ:')
486 print('snapshot map differ:')
491 print(' expected: %s' % snapshotmap15)
487 print(' expected: %s' % snapshotmap15)
492 print(' got: %s' % result15)
488 print(' got: %s' % result15)
493
489
494
490
495 def maintest():
491 def maintest():
496 with newtransaction() as tr:
492 with newtransaction() as tr:
497 rl = newrevlog(recreate=True)
493 rl = newrevlog(recreate=True)
498 expected = writecases(rl, tr)
494 expected = writecases(rl, tr)
499 checkrevlog(rl, expected)
495 checkrevlog(rl, expected)
500 print('local test passed')
496 print('local test passed')
501 # Copy via revlog.addgroup
497 # Copy via revlog.addgroup
502 rl1 = addgroupcopy(rl, tr)
498 rl1 = addgroupcopy(rl, tr)
503 checkrevlog(rl1, expected)
499 checkrevlog(rl1, expected)
504 rl2 = addgroupcopy(rl, tr, optimaldelta=False)
500 rl2 = addgroupcopy(rl, tr, optimaldelta=False)
505 checkrevlog(rl2, expected)
501 checkrevlog(rl2, expected)
506 print('addgroupcopy test passed')
502 print('addgroupcopy test passed')
507 # Copy via revlog.clone
503 # Copy via revlog.clone
508 rl3 = newrevlog(name=b'_destrevlog3', recreate=True)
504 rl3 = newrevlog(name=b'_destrevlog3', recreate=True)
509 rl.clone(tr, rl3)
505 rl.clone(tr, rl3)
510 checkrevlog(rl3, expected)
506 checkrevlog(rl3, expected)
511 print('clone test passed')
507 print('clone test passed')
512 # Copy via low-level revlog._addrevision
508 # Copy via low-level revlog._addrevision
513 rl4 = lowlevelcopy(rl, tr)
509 rl4 = lowlevelcopy(rl, tr)
514 checkrevlog(rl4, expected)
510 checkrevlog(rl4, expected)
515 print('lowlevelcopy test passed')
511 print('lowlevelcopy test passed')
516 slicingtest(rl)
512 slicingtest(rl)
517 print('slicing test passed')
513 print('slicing test passed')
518 rl5 = makesnapshot(tr)
514 rl5 = makesnapshot(tr)
519 issnapshottest(rl5)
515 issnapshottest(rl5)
520 print('issnapshot test passed')
516 print('issnapshot test passed')
521 findsnapshottest(rl5)
517 findsnapshottest(rl5)
522 print('findsnapshot test passed')
518 print('findsnapshot test passed')
523
519
524
520
525 try:
521 try:
526 maintest()
522 maintest()
527 except Exception as ex:
523 except Exception as ex:
528 abort('crashed: %s' % ex)
524 abort('crashed: %s' % ex)
General Comments 0
You need to be logged in to leave comments. Login now