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