##// END OF EJS Templates
testing: switch to inserting deltas...
Gregory Szorc -
r40359:2c0aa02e default
parent child Browse files
Show More
@@ -1,1332 +1,1331
1 # storage.py - Testing of storage primitives.
1 # storage.py - Testing of storage primitives.
2 #
2 #
3 # Copyright 2018 Gregory Szorc <gregory.szorc@gmail.com>
3 # Copyright 2018 Gregory Szorc <gregory.szorc@gmail.com>
4 #
4 #
5 # This software may be used and distributed according to the terms of the
5 # This software may be used and distributed according to the terms of the
6 # GNU General Public License version 2 or any later version.
6 # GNU General Public License version 2 or any later version.
7
7
8 from __future__ import absolute_import
8 from __future__ import absolute_import
9
9
10 import unittest
10 import unittest
11
11
12 from ..node import (
12 from ..node import (
13 hex,
13 hex,
14 nullid,
14 nullid,
15 nullrev,
15 nullrev,
16 )
16 )
17 from .. import (
17 from .. import (
18 error,
18 error,
19 mdiff,
19 mdiff,
20 repository,
20 repository,
21 )
21 )
22 from ..utils import (
22 from ..utils import (
23 storageutil,
23 storageutil,
24 )
24 )
25
25
26 class basetestcase(unittest.TestCase):
26 class basetestcase(unittest.TestCase):
27 if not getattr(unittest.TestCase, r'assertRaisesRegex', False):
27 if not getattr(unittest.TestCase, r'assertRaisesRegex', False):
28 assertRaisesRegex = (# camelcase-required
28 assertRaisesRegex = (# camelcase-required
29 unittest.TestCase.assertRaisesRegexp)
29 unittest.TestCase.assertRaisesRegexp)
30
30
31 class ifileindextests(basetestcase):
31 class ifileindextests(basetestcase):
32 """Generic tests for the ifileindex interface.
32 """Generic tests for the ifileindex interface.
33
33
34 All file storage backends for index data should conform to the tests in this
34 All file storage backends for index data should conform to the tests in this
35 class.
35 class.
36
36
37 Use ``makeifileindextests()`` to create an instance of this type.
37 Use ``makeifileindextests()`` to create an instance of this type.
38 """
38 """
39 def testempty(self):
39 def testempty(self):
40 f = self._makefilefn()
40 f = self._makefilefn()
41 self.assertEqual(len(f), 0, 'new file store has 0 length by default')
41 self.assertEqual(len(f), 0, 'new file store has 0 length by default')
42 self.assertEqual(list(f), [], 'iter yields nothing by default')
42 self.assertEqual(list(f), [], 'iter yields nothing by default')
43
43
44 gen = iter(f)
44 gen = iter(f)
45 with self.assertRaises(StopIteration):
45 with self.assertRaises(StopIteration):
46 next(gen)
46 next(gen)
47
47
48 # revs() should evaluate to an empty list.
48 # revs() should evaluate to an empty list.
49 self.assertEqual(list(f.revs()), [])
49 self.assertEqual(list(f.revs()), [])
50
50
51 revs = iter(f.revs())
51 revs = iter(f.revs())
52 with self.assertRaises(StopIteration):
52 with self.assertRaises(StopIteration):
53 next(revs)
53 next(revs)
54
54
55 self.assertEqual(list(f.revs(start=20)), [])
55 self.assertEqual(list(f.revs(start=20)), [])
56
56
57 # parents() and parentrevs() work with nullid/nullrev.
57 # parents() and parentrevs() work with nullid/nullrev.
58 self.assertEqual(f.parents(nullid), (nullid, nullid))
58 self.assertEqual(f.parents(nullid), (nullid, nullid))
59 self.assertEqual(f.parentrevs(nullrev), (nullrev, nullrev))
59 self.assertEqual(f.parentrevs(nullrev), (nullrev, nullrev))
60
60
61 with self.assertRaises(error.LookupError):
61 with self.assertRaises(error.LookupError):
62 f.parents(b'\x01' * 20)
62 f.parents(b'\x01' * 20)
63
63
64 for i in range(-5, 5):
64 for i in range(-5, 5):
65 if i == nullrev:
65 if i == nullrev:
66 continue
66 continue
67
67
68 with self.assertRaises(IndexError):
68 with self.assertRaises(IndexError):
69 f.parentrevs(i)
69 f.parentrevs(i)
70
70
71 # nullid/nullrev lookup always works.
71 # nullid/nullrev lookup always works.
72 self.assertEqual(f.rev(nullid), nullrev)
72 self.assertEqual(f.rev(nullid), nullrev)
73 self.assertEqual(f.node(nullrev), nullid)
73 self.assertEqual(f.node(nullrev), nullid)
74
74
75 with self.assertRaises(error.LookupError):
75 with self.assertRaises(error.LookupError):
76 f.rev(b'\x01' * 20)
76 f.rev(b'\x01' * 20)
77
77
78 for i in range(-5, 5):
78 for i in range(-5, 5):
79 if i == nullrev:
79 if i == nullrev:
80 continue
80 continue
81
81
82 with self.assertRaises(IndexError):
82 with self.assertRaises(IndexError):
83 f.node(i)
83 f.node(i)
84
84
85 self.assertEqual(f.lookup(nullid), nullid)
85 self.assertEqual(f.lookup(nullid), nullid)
86 self.assertEqual(f.lookup(nullrev), nullid)
86 self.assertEqual(f.lookup(nullrev), nullid)
87 self.assertEqual(f.lookup(hex(nullid)), nullid)
87 self.assertEqual(f.lookup(hex(nullid)), nullid)
88 self.assertEqual(f.lookup(b'%d' % nullrev), nullid)
88 self.assertEqual(f.lookup(b'%d' % nullrev), nullid)
89
89
90 with self.assertRaises(error.LookupError):
90 with self.assertRaises(error.LookupError):
91 f.lookup(b'badvalue')
91 f.lookup(b'badvalue')
92
92
93 with self.assertRaises(error.LookupError):
93 with self.assertRaises(error.LookupError):
94 f.lookup(hex(nullid)[0:12])
94 f.lookup(hex(nullid)[0:12])
95
95
96 with self.assertRaises(error.LookupError):
96 with self.assertRaises(error.LookupError):
97 f.lookup(b'-2')
97 f.lookup(b'-2')
98
98
99 with self.assertRaises(error.LookupError):
99 with self.assertRaises(error.LookupError):
100 f.lookup(b'0')
100 f.lookup(b'0')
101
101
102 with self.assertRaises(error.LookupError):
102 with self.assertRaises(error.LookupError):
103 f.lookup(b'1')
103 f.lookup(b'1')
104
104
105 with self.assertRaises(error.LookupError):
105 with self.assertRaises(error.LookupError):
106 f.lookup(b'11111111111111111111111111111111111111')
106 f.lookup(b'11111111111111111111111111111111111111')
107
107
108 for i in range(-5, 5):
108 for i in range(-5, 5):
109 if i == nullrev:
109 if i == nullrev:
110 continue
110 continue
111
111
112 with self.assertRaises(LookupError):
112 with self.assertRaises(LookupError):
113 f.lookup(i)
113 f.lookup(i)
114
114
115 self.assertEqual(f.linkrev(nullrev), nullrev)
115 self.assertEqual(f.linkrev(nullrev), nullrev)
116
116
117 for i in range(-5, 5):
117 for i in range(-5, 5):
118 if i == nullrev:
118 if i == nullrev:
119 continue
119 continue
120
120
121 with self.assertRaises(IndexError):
121 with self.assertRaises(IndexError):
122 f.linkrev(i)
122 f.linkrev(i)
123
123
124 self.assertFalse(f.iscensored(nullrev))
124 self.assertFalse(f.iscensored(nullrev))
125
125
126 for i in range(-5, 5):
126 for i in range(-5, 5):
127 if i == nullrev:
127 if i == nullrev:
128 continue
128 continue
129
129
130 with self.assertRaises(IndexError):
130 with self.assertRaises(IndexError):
131 f.iscensored(i)
131 f.iscensored(i)
132
132
133 self.assertEqual(list(f.commonancestorsheads(nullid, nullid)), [])
133 self.assertEqual(list(f.commonancestorsheads(nullid, nullid)), [])
134
134
135 with self.assertRaises(ValueError):
135 with self.assertRaises(ValueError):
136 self.assertEqual(list(f.descendants([])), [])
136 self.assertEqual(list(f.descendants([])), [])
137
137
138 self.assertEqual(list(f.descendants([nullrev])), [])
138 self.assertEqual(list(f.descendants([nullrev])), [])
139
139
140 self.assertEqual(f.heads(), [nullid])
140 self.assertEqual(f.heads(), [nullid])
141 self.assertEqual(f.heads(nullid), [nullid])
141 self.assertEqual(f.heads(nullid), [nullid])
142 self.assertEqual(f.heads(None, [nullid]), [nullid])
142 self.assertEqual(f.heads(None, [nullid]), [nullid])
143 self.assertEqual(f.heads(nullid, [nullid]), [nullid])
143 self.assertEqual(f.heads(nullid, [nullid]), [nullid])
144
144
145 self.assertEqual(f.children(nullid), [])
145 self.assertEqual(f.children(nullid), [])
146
146
147 with self.assertRaises(error.LookupError):
147 with self.assertRaises(error.LookupError):
148 f.children(b'\x01' * 20)
148 f.children(b'\x01' * 20)
149
149
150 def testsinglerevision(self):
150 def testsinglerevision(self):
151 f = self._makefilefn()
151 f = self._makefilefn()
152 with self._maketransactionfn() as tr:
152 with self._maketransactionfn() as tr:
153 node = f.add(b'initial', None, tr, 0, nullid, nullid)
153 node = f.add(b'initial', None, tr, 0, nullid, nullid)
154
154
155 self.assertEqual(len(f), 1)
155 self.assertEqual(len(f), 1)
156 self.assertEqual(list(f), [0])
156 self.assertEqual(list(f), [0])
157
157
158 gen = iter(f)
158 gen = iter(f)
159 self.assertEqual(next(gen), 0)
159 self.assertEqual(next(gen), 0)
160
160
161 with self.assertRaises(StopIteration):
161 with self.assertRaises(StopIteration):
162 next(gen)
162 next(gen)
163
163
164 self.assertEqual(list(f.revs()), [0])
164 self.assertEqual(list(f.revs()), [0])
165 self.assertEqual(list(f.revs(start=1)), [])
165 self.assertEqual(list(f.revs(start=1)), [])
166 self.assertEqual(list(f.revs(start=0)), [0])
166 self.assertEqual(list(f.revs(start=0)), [0])
167 self.assertEqual(list(f.revs(stop=0)), [0])
167 self.assertEqual(list(f.revs(stop=0)), [0])
168 self.assertEqual(list(f.revs(stop=1)), [0])
168 self.assertEqual(list(f.revs(stop=1)), [0])
169 self.assertEqual(list(f.revs(1, 1)), [])
169 self.assertEqual(list(f.revs(1, 1)), [])
170 # TODO buggy
170 # TODO buggy
171 self.assertEqual(list(f.revs(1, 0)), [1, 0])
171 self.assertEqual(list(f.revs(1, 0)), [1, 0])
172 self.assertEqual(list(f.revs(2, 0)), [2, 1, 0])
172 self.assertEqual(list(f.revs(2, 0)), [2, 1, 0])
173
173
174 self.assertEqual(f.parents(node), (nullid, nullid))
174 self.assertEqual(f.parents(node), (nullid, nullid))
175 self.assertEqual(f.parentrevs(0), (nullrev, nullrev))
175 self.assertEqual(f.parentrevs(0), (nullrev, nullrev))
176
176
177 with self.assertRaises(error.LookupError):
177 with self.assertRaises(error.LookupError):
178 f.parents(b'\x01' * 20)
178 f.parents(b'\x01' * 20)
179
179
180 with self.assertRaises(IndexError):
180 with self.assertRaises(IndexError):
181 f.parentrevs(1)
181 f.parentrevs(1)
182
182
183 self.assertEqual(f.rev(node), 0)
183 self.assertEqual(f.rev(node), 0)
184
184
185 with self.assertRaises(error.LookupError):
185 with self.assertRaises(error.LookupError):
186 f.rev(b'\x01' * 20)
186 f.rev(b'\x01' * 20)
187
187
188 self.assertEqual(f.node(0), node)
188 self.assertEqual(f.node(0), node)
189
189
190 with self.assertRaises(IndexError):
190 with self.assertRaises(IndexError):
191 f.node(1)
191 f.node(1)
192
192
193 self.assertEqual(f.lookup(node), node)
193 self.assertEqual(f.lookup(node), node)
194 self.assertEqual(f.lookup(0), node)
194 self.assertEqual(f.lookup(0), node)
195 self.assertEqual(f.lookup(-1), nullid)
195 self.assertEqual(f.lookup(-1), nullid)
196 self.assertEqual(f.lookup(b'0'), node)
196 self.assertEqual(f.lookup(b'0'), node)
197 self.assertEqual(f.lookup(hex(node)), node)
197 self.assertEqual(f.lookup(hex(node)), node)
198
198
199 with self.assertRaises(error.LookupError):
199 with self.assertRaises(error.LookupError):
200 f.lookup(hex(node)[0:12])
200 f.lookup(hex(node)[0:12])
201
201
202 with self.assertRaises(error.LookupError):
202 with self.assertRaises(error.LookupError):
203 f.lookup(-2)
203 f.lookup(-2)
204
204
205 with self.assertRaises(error.LookupError):
205 with self.assertRaises(error.LookupError):
206 f.lookup(b'-2')
206 f.lookup(b'-2')
207
207
208 with self.assertRaises(error.LookupError):
208 with self.assertRaises(error.LookupError):
209 f.lookup(1)
209 f.lookup(1)
210
210
211 with self.assertRaises(error.LookupError):
211 with self.assertRaises(error.LookupError):
212 f.lookup(b'1')
212 f.lookup(b'1')
213
213
214 self.assertEqual(f.linkrev(0), 0)
214 self.assertEqual(f.linkrev(0), 0)
215
215
216 with self.assertRaises(IndexError):
216 with self.assertRaises(IndexError):
217 f.linkrev(1)
217 f.linkrev(1)
218
218
219 self.assertFalse(f.iscensored(0))
219 self.assertFalse(f.iscensored(0))
220
220
221 with self.assertRaises(IndexError):
221 with self.assertRaises(IndexError):
222 f.iscensored(1)
222 f.iscensored(1)
223
223
224 self.assertEqual(list(f.descendants([0])), [])
224 self.assertEqual(list(f.descendants([0])), [])
225
225
226 self.assertEqual(f.heads(), [node])
226 self.assertEqual(f.heads(), [node])
227 self.assertEqual(f.heads(node), [node])
227 self.assertEqual(f.heads(node), [node])
228 self.assertEqual(f.heads(stop=[node]), [node])
228 self.assertEqual(f.heads(stop=[node]), [node])
229
229
230 with self.assertRaises(error.LookupError):
230 with self.assertRaises(error.LookupError):
231 f.heads(stop=[b'\x01' * 20])
231 f.heads(stop=[b'\x01' * 20])
232
232
233 self.assertEqual(f.children(node), [])
233 self.assertEqual(f.children(node), [])
234
234
235 def testmultiplerevisions(self):
235 def testmultiplerevisions(self):
236 fulltext0 = b'x' * 1024
236 fulltext0 = b'x' * 1024
237 fulltext1 = fulltext0 + b'y'
237 fulltext1 = fulltext0 + b'y'
238 fulltext2 = b'y' + fulltext0 + b'z'
238 fulltext2 = b'y' + fulltext0 + b'z'
239
239
240 f = self._makefilefn()
240 f = self._makefilefn()
241 with self._maketransactionfn() as tr:
241 with self._maketransactionfn() as tr:
242 node0 = f.add(fulltext0, None, tr, 0, nullid, nullid)
242 node0 = f.add(fulltext0, None, tr, 0, nullid, nullid)
243 node1 = f.add(fulltext1, None, tr, 1, node0, nullid)
243 node1 = f.add(fulltext1, None, tr, 1, node0, nullid)
244 node2 = f.add(fulltext2, None, tr, 3, node1, nullid)
244 node2 = f.add(fulltext2, None, tr, 3, node1, nullid)
245
245
246 self.assertEqual(len(f), 3)
246 self.assertEqual(len(f), 3)
247 self.assertEqual(list(f), [0, 1, 2])
247 self.assertEqual(list(f), [0, 1, 2])
248
248
249 gen = iter(f)
249 gen = iter(f)
250 self.assertEqual(next(gen), 0)
250 self.assertEqual(next(gen), 0)
251 self.assertEqual(next(gen), 1)
251 self.assertEqual(next(gen), 1)
252 self.assertEqual(next(gen), 2)
252 self.assertEqual(next(gen), 2)
253
253
254 with self.assertRaises(StopIteration):
254 with self.assertRaises(StopIteration):
255 next(gen)
255 next(gen)
256
256
257 self.assertEqual(list(f.revs()), [0, 1, 2])
257 self.assertEqual(list(f.revs()), [0, 1, 2])
258 self.assertEqual(list(f.revs(0)), [0, 1, 2])
258 self.assertEqual(list(f.revs(0)), [0, 1, 2])
259 self.assertEqual(list(f.revs(1)), [1, 2])
259 self.assertEqual(list(f.revs(1)), [1, 2])
260 self.assertEqual(list(f.revs(2)), [2])
260 self.assertEqual(list(f.revs(2)), [2])
261 self.assertEqual(list(f.revs(3)), [])
261 self.assertEqual(list(f.revs(3)), [])
262 self.assertEqual(list(f.revs(stop=1)), [0, 1])
262 self.assertEqual(list(f.revs(stop=1)), [0, 1])
263 self.assertEqual(list(f.revs(stop=2)), [0, 1, 2])
263 self.assertEqual(list(f.revs(stop=2)), [0, 1, 2])
264 self.assertEqual(list(f.revs(stop=3)), [0, 1, 2])
264 self.assertEqual(list(f.revs(stop=3)), [0, 1, 2])
265 self.assertEqual(list(f.revs(2, 0)), [2, 1, 0])
265 self.assertEqual(list(f.revs(2, 0)), [2, 1, 0])
266 self.assertEqual(list(f.revs(2, 1)), [2, 1])
266 self.assertEqual(list(f.revs(2, 1)), [2, 1])
267 # TODO this is wrong
267 # TODO this is wrong
268 self.assertEqual(list(f.revs(3, 2)), [3, 2])
268 self.assertEqual(list(f.revs(3, 2)), [3, 2])
269
269
270 self.assertEqual(f.parents(node0), (nullid, nullid))
270 self.assertEqual(f.parents(node0), (nullid, nullid))
271 self.assertEqual(f.parents(node1), (node0, nullid))
271 self.assertEqual(f.parents(node1), (node0, nullid))
272 self.assertEqual(f.parents(node2), (node1, nullid))
272 self.assertEqual(f.parents(node2), (node1, nullid))
273
273
274 self.assertEqual(f.parentrevs(0), (nullrev, nullrev))
274 self.assertEqual(f.parentrevs(0), (nullrev, nullrev))
275 self.assertEqual(f.parentrevs(1), (0, nullrev))
275 self.assertEqual(f.parentrevs(1), (0, nullrev))
276 self.assertEqual(f.parentrevs(2), (1, nullrev))
276 self.assertEqual(f.parentrevs(2), (1, nullrev))
277
277
278 self.assertEqual(f.rev(node0), 0)
278 self.assertEqual(f.rev(node0), 0)
279 self.assertEqual(f.rev(node1), 1)
279 self.assertEqual(f.rev(node1), 1)
280 self.assertEqual(f.rev(node2), 2)
280 self.assertEqual(f.rev(node2), 2)
281
281
282 with self.assertRaises(error.LookupError):
282 with self.assertRaises(error.LookupError):
283 f.rev(b'\x01' * 20)
283 f.rev(b'\x01' * 20)
284
284
285 self.assertEqual(f.node(0), node0)
285 self.assertEqual(f.node(0), node0)
286 self.assertEqual(f.node(1), node1)
286 self.assertEqual(f.node(1), node1)
287 self.assertEqual(f.node(2), node2)
287 self.assertEqual(f.node(2), node2)
288
288
289 with self.assertRaises(IndexError):
289 with self.assertRaises(IndexError):
290 f.node(3)
290 f.node(3)
291
291
292 self.assertEqual(f.lookup(node0), node0)
292 self.assertEqual(f.lookup(node0), node0)
293 self.assertEqual(f.lookup(0), node0)
293 self.assertEqual(f.lookup(0), node0)
294 self.assertEqual(f.lookup(b'0'), node0)
294 self.assertEqual(f.lookup(b'0'), node0)
295 self.assertEqual(f.lookup(hex(node0)), node0)
295 self.assertEqual(f.lookup(hex(node0)), node0)
296
296
297 self.assertEqual(f.lookup(node1), node1)
297 self.assertEqual(f.lookup(node1), node1)
298 self.assertEqual(f.lookup(1), node1)
298 self.assertEqual(f.lookup(1), node1)
299 self.assertEqual(f.lookup(b'1'), node1)
299 self.assertEqual(f.lookup(b'1'), node1)
300 self.assertEqual(f.lookup(hex(node1)), node1)
300 self.assertEqual(f.lookup(hex(node1)), node1)
301
301
302 self.assertEqual(f.linkrev(0), 0)
302 self.assertEqual(f.linkrev(0), 0)
303 self.assertEqual(f.linkrev(1), 1)
303 self.assertEqual(f.linkrev(1), 1)
304 self.assertEqual(f.linkrev(2), 3)
304 self.assertEqual(f.linkrev(2), 3)
305
305
306 with self.assertRaises(IndexError):
306 with self.assertRaises(IndexError):
307 f.linkrev(3)
307 f.linkrev(3)
308
308
309 self.assertFalse(f.iscensored(0))
309 self.assertFalse(f.iscensored(0))
310 self.assertFalse(f.iscensored(1))
310 self.assertFalse(f.iscensored(1))
311 self.assertFalse(f.iscensored(2))
311 self.assertFalse(f.iscensored(2))
312
312
313 with self.assertRaises(IndexError):
313 with self.assertRaises(IndexError):
314 f.iscensored(3)
314 f.iscensored(3)
315
315
316 self.assertEqual(f.commonancestorsheads(node1, nullid), [])
316 self.assertEqual(f.commonancestorsheads(node1, nullid), [])
317 self.assertEqual(f.commonancestorsheads(node1, node0), [node0])
317 self.assertEqual(f.commonancestorsheads(node1, node0), [node0])
318 self.assertEqual(f.commonancestorsheads(node1, node1), [node1])
318 self.assertEqual(f.commonancestorsheads(node1, node1), [node1])
319 self.assertEqual(f.commonancestorsheads(node0, node1), [node0])
319 self.assertEqual(f.commonancestorsheads(node0, node1), [node0])
320 self.assertEqual(f.commonancestorsheads(node1, node2), [node1])
320 self.assertEqual(f.commonancestorsheads(node1, node2), [node1])
321 self.assertEqual(f.commonancestorsheads(node2, node1), [node1])
321 self.assertEqual(f.commonancestorsheads(node2, node1), [node1])
322
322
323 self.assertEqual(list(f.descendants([0])), [1, 2])
323 self.assertEqual(list(f.descendants([0])), [1, 2])
324 self.assertEqual(list(f.descendants([1])), [2])
324 self.assertEqual(list(f.descendants([1])), [2])
325 self.assertEqual(list(f.descendants([0, 1])), [1, 2])
325 self.assertEqual(list(f.descendants([0, 1])), [1, 2])
326
326
327 self.assertEqual(f.heads(), [node2])
327 self.assertEqual(f.heads(), [node2])
328 self.assertEqual(f.heads(node0), [node2])
328 self.assertEqual(f.heads(node0), [node2])
329 self.assertEqual(f.heads(node1), [node2])
329 self.assertEqual(f.heads(node1), [node2])
330 self.assertEqual(f.heads(node2), [node2])
330 self.assertEqual(f.heads(node2), [node2])
331
331
332 # TODO this behavior seems wonky. Is it correct? If so, the
332 # TODO this behavior seems wonky. Is it correct? If so, the
333 # docstring for heads() should be updated to reflect desired
333 # docstring for heads() should be updated to reflect desired
334 # behavior.
334 # behavior.
335 self.assertEqual(f.heads(stop=[node1]), [node1, node2])
335 self.assertEqual(f.heads(stop=[node1]), [node1, node2])
336 self.assertEqual(f.heads(stop=[node0]), [node0, node2])
336 self.assertEqual(f.heads(stop=[node0]), [node0, node2])
337 self.assertEqual(f.heads(stop=[node1, node2]), [node1, node2])
337 self.assertEqual(f.heads(stop=[node1, node2]), [node1, node2])
338
338
339 with self.assertRaises(error.LookupError):
339 with self.assertRaises(error.LookupError):
340 f.heads(stop=[b'\x01' * 20])
340 f.heads(stop=[b'\x01' * 20])
341
341
342 self.assertEqual(f.children(node0), [node1])
342 self.assertEqual(f.children(node0), [node1])
343 self.assertEqual(f.children(node1), [node2])
343 self.assertEqual(f.children(node1), [node2])
344 self.assertEqual(f.children(node2), [])
344 self.assertEqual(f.children(node2), [])
345
345
346 def testmultipleheads(self):
346 def testmultipleheads(self):
347 f = self._makefilefn()
347 f = self._makefilefn()
348
348
349 with self._maketransactionfn() as tr:
349 with self._maketransactionfn() as tr:
350 node0 = f.add(b'0', None, tr, 0, nullid, nullid)
350 node0 = f.add(b'0', None, tr, 0, nullid, nullid)
351 node1 = f.add(b'1', None, tr, 1, node0, nullid)
351 node1 = f.add(b'1', None, tr, 1, node0, nullid)
352 node2 = f.add(b'2', None, tr, 2, node1, nullid)
352 node2 = f.add(b'2', None, tr, 2, node1, nullid)
353 node3 = f.add(b'3', None, tr, 3, node0, nullid)
353 node3 = f.add(b'3', None, tr, 3, node0, nullid)
354 node4 = f.add(b'4', None, tr, 4, node3, nullid)
354 node4 = f.add(b'4', None, tr, 4, node3, nullid)
355 node5 = f.add(b'5', None, tr, 5, node0, nullid)
355 node5 = f.add(b'5', None, tr, 5, node0, nullid)
356
356
357 self.assertEqual(len(f), 6)
357 self.assertEqual(len(f), 6)
358
358
359 self.assertEqual(list(f.descendants([0])), [1, 2, 3, 4, 5])
359 self.assertEqual(list(f.descendants([0])), [1, 2, 3, 4, 5])
360 self.assertEqual(list(f.descendants([1])), [2])
360 self.assertEqual(list(f.descendants([1])), [2])
361 self.assertEqual(list(f.descendants([2])), [])
361 self.assertEqual(list(f.descendants([2])), [])
362 self.assertEqual(list(f.descendants([3])), [4])
362 self.assertEqual(list(f.descendants([3])), [4])
363 self.assertEqual(list(f.descendants([0, 1])), [1, 2, 3, 4, 5])
363 self.assertEqual(list(f.descendants([0, 1])), [1, 2, 3, 4, 5])
364 self.assertEqual(list(f.descendants([1, 3])), [2, 4])
364 self.assertEqual(list(f.descendants([1, 3])), [2, 4])
365
365
366 self.assertEqual(f.heads(), [node2, node4, node5])
366 self.assertEqual(f.heads(), [node2, node4, node5])
367 self.assertEqual(f.heads(node0), [node2, node4, node5])
367 self.assertEqual(f.heads(node0), [node2, node4, node5])
368 self.assertEqual(f.heads(node1), [node2])
368 self.assertEqual(f.heads(node1), [node2])
369 self.assertEqual(f.heads(node2), [node2])
369 self.assertEqual(f.heads(node2), [node2])
370 self.assertEqual(f.heads(node3), [node4])
370 self.assertEqual(f.heads(node3), [node4])
371 self.assertEqual(f.heads(node4), [node4])
371 self.assertEqual(f.heads(node4), [node4])
372 self.assertEqual(f.heads(node5), [node5])
372 self.assertEqual(f.heads(node5), [node5])
373
373
374 # TODO this seems wrong.
374 # TODO this seems wrong.
375 self.assertEqual(f.heads(stop=[node0]), [node0, node2, node4, node5])
375 self.assertEqual(f.heads(stop=[node0]), [node0, node2, node4, node5])
376 self.assertEqual(f.heads(stop=[node1]), [node1, node2, node4, node5])
376 self.assertEqual(f.heads(stop=[node1]), [node1, node2, node4, node5])
377
377
378 self.assertEqual(f.children(node0), [node1, node3, node5])
378 self.assertEqual(f.children(node0), [node1, node3, node5])
379 self.assertEqual(f.children(node1), [node2])
379 self.assertEqual(f.children(node1), [node2])
380 self.assertEqual(f.children(node2), [])
380 self.assertEqual(f.children(node2), [])
381 self.assertEqual(f.children(node3), [node4])
381 self.assertEqual(f.children(node3), [node4])
382 self.assertEqual(f.children(node4), [])
382 self.assertEqual(f.children(node4), [])
383 self.assertEqual(f.children(node5), [])
383 self.assertEqual(f.children(node5), [])
384
384
385 class ifiledatatests(basetestcase):
385 class ifiledatatests(basetestcase):
386 """Generic tests for the ifiledata interface.
386 """Generic tests for the ifiledata interface.
387
387
388 All file storage backends for data should conform to the tests in this
388 All file storage backends for data should conform to the tests in this
389 class.
389 class.
390
390
391 Use ``makeifiledatatests()`` to create an instance of this type.
391 Use ``makeifiledatatests()`` to create an instance of this type.
392 """
392 """
393 def testempty(self):
393 def testempty(self):
394 f = self._makefilefn()
394 f = self._makefilefn()
395
395
396 self.assertEqual(f.storageinfo(), {})
396 self.assertEqual(f.storageinfo(), {})
397 self.assertEqual(f.storageinfo(revisionscount=True, trackedsize=True),
397 self.assertEqual(f.storageinfo(revisionscount=True, trackedsize=True),
398 {'revisionscount': 0, 'trackedsize': 0})
398 {'revisionscount': 0, 'trackedsize': 0})
399
399
400 self.assertEqual(f.size(nullrev), 0)
400 self.assertEqual(f.size(nullrev), 0)
401
401
402 for i in range(-5, 5):
402 for i in range(-5, 5):
403 if i == nullrev:
403 if i == nullrev:
404 continue
404 continue
405
405
406 with self.assertRaises(IndexError):
406 with self.assertRaises(IndexError):
407 f.size(i)
407 f.size(i)
408
408
409 self.assertEqual(f.revision(nullid), b'')
409 self.assertEqual(f.revision(nullid), b'')
410 self.assertEqual(f.revision(nullid, raw=True), b'')
410 self.assertEqual(f.revision(nullid, raw=True), b'')
411
411
412 with self.assertRaises(error.LookupError):
412 with self.assertRaises(error.LookupError):
413 f.revision(b'\x01' * 20)
413 f.revision(b'\x01' * 20)
414
414
415 self.assertEqual(f.read(nullid), b'')
415 self.assertEqual(f.read(nullid), b'')
416
416
417 with self.assertRaises(error.LookupError):
417 with self.assertRaises(error.LookupError):
418 f.read(b'\x01' * 20)
418 f.read(b'\x01' * 20)
419
419
420 self.assertFalse(f.renamed(nullid))
420 self.assertFalse(f.renamed(nullid))
421
421
422 with self.assertRaises(error.LookupError):
422 with self.assertRaises(error.LookupError):
423 f.read(b'\x01' * 20)
423 f.read(b'\x01' * 20)
424
424
425 self.assertTrue(f.cmp(nullid, b''))
425 self.assertTrue(f.cmp(nullid, b''))
426 self.assertTrue(f.cmp(nullid, b'foo'))
426 self.assertTrue(f.cmp(nullid, b'foo'))
427
427
428 with self.assertRaises(error.LookupError):
428 with self.assertRaises(error.LookupError):
429 f.cmp(b'\x01' * 20, b'irrelevant')
429 f.cmp(b'\x01' * 20, b'irrelevant')
430
430
431 # Emitting empty list is an empty generator.
431 # Emitting empty list is an empty generator.
432 gen = f.emitrevisions([])
432 gen = f.emitrevisions([])
433 with self.assertRaises(StopIteration):
433 with self.assertRaises(StopIteration):
434 next(gen)
434 next(gen)
435
435
436 # Emitting null node yields nothing.
436 # Emitting null node yields nothing.
437 gen = f.emitrevisions([nullid])
437 gen = f.emitrevisions([nullid])
438 with self.assertRaises(StopIteration):
438 with self.assertRaises(StopIteration):
439 next(gen)
439 next(gen)
440
440
441 # Requesting unknown node fails.
441 # Requesting unknown node fails.
442 with self.assertRaises(error.LookupError):
442 with self.assertRaises(error.LookupError):
443 list(f.emitrevisions([b'\x01' * 20]))
443 list(f.emitrevisions([b'\x01' * 20]))
444
444
445 def testsinglerevision(self):
445 def testsinglerevision(self):
446 fulltext = b'initial'
446 fulltext = b'initial'
447
447
448 f = self._makefilefn()
448 f = self._makefilefn()
449 with self._maketransactionfn() as tr:
449 with self._maketransactionfn() as tr:
450 node = f.add(fulltext, None, tr, 0, nullid, nullid)
450 node = f.add(fulltext, None, tr, 0, nullid, nullid)
451
451
452 self.assertEqual(f.storageinfo(), {})
452 self.assertEqual(f.storageinfo(), {})
453 self.assertEqual(f.storageinfo(revisionscount=True, trackedsize=True),
453 self.assertEqual(f.storageinfo(revisionscount=True, trackedsize=True),
454 {'revisionscount': 1, 'trackedsize': len(fulltext)})
454 {'revisionscount': 1, 'trackedsize': len(fulltext)})
455
455
456 self.assertEqual(f.size(0), len(fulltext))
456 self.assertEqual(f.size(0), len(fulltext))
457
457
458 with self.assertRaises(IndexError):
458 with self.assertRaises(IndexError):
459 f.size(1)
459 f.size(1)
460
460
461 self.assertEqual(f.revision(node), fulltext)
461 self.assertEqual(f.revision(node), fulltext)
462 self.assertEqual(f.revision(node, raw=True), fulltext)
462 self.assertEqual(f.revision(node, raw=True), fulltext)
463
463
464 self.assertEqual(f.read(node), fulltext)
464 self.assertEqual(f.read(node), fulltext)
465
465
466 self.assertFalse(f.renamed(node))
466 self.assertFalse(f.renamed(node))
467
467
468 self.assertFalse(f.cmp(node, fulltext))
468 self.assertFalse(f.cmp(node, fulltext))
469 self.assertTrue(f.cmp(node, fulltext + b'extra'))
469 self.assertTrue(f.cmp(node, fulltext + b'extra'))
470
470
471 # Emitting a single revision works.
471 # Emitting a single revision works.
472 gen = f.emitrevisions([node])
472 gen = f.emitrevisions([node])
473 rev = next(gen)
473 rev = next(gen)
474
474
475 self.assertEqual(rev.node, node)
475 self.assertEqual(rev.node, node)
476 self.assertEqual(rev.p1node, nullid)
476 self.assertEqual(rev.p1node, nullid)
477 self.assertEqual(rev.p2node, nullid)
477 self.assertEqual(rev.p2node, nullid)
478 self.assertIsNone(rev.linknode)
478 self.assertIsNone(rev.linknode)
479 self.assertEqual(rev.basenode, nullid)
479 self.assertEqual(rev.basenode, nullid)
480 self.assertIsNone(rev.baserevisionsize)
480 self.assertIsNone(rev.baserevisionsize)
481 self.assertIsNone(rev.revision)
481 self.assertIsNone(rev.revision)
482 self.assertIsNone(rev.delta)
482 self.assertIsNone(rev.delta)
483
483
484 with self.assertRaises(StopIteration):
484 with self.assertRaises(StopIteration):
485 next(gen)
485 next(gen)
486
486
487 # Requesting revision data works.
487 # Requesting revision data works.
488 gen = f.emitrevisions([node], revisiondata=True)
488 gen = f.emitrevisions([node], revisiondata=True)
489 rev = next(gen)
489 rev = next(gen)
490
490
491 self.assertEqual(rev.node, node)
491 self.assertEqual(rev.node, node)
492 self.assertEqual(rev.p1node, nullid)
492 self.assertEqual(rev.p1node, nullid)
493 self.assertEqual(rev.p2node, nullid)
493 self.assertEqual(rev.p2node, nullid)
494 self.assertIsNone(rev.linknode)
494 self.assertIsNone(rev.linknode)
495 self.assertEqual(rev.basenode, nullid)
495 self.assertEqual(rev.basenode, nullid)
496 self.assertIsNone(rev.baserevisionsize)
496 self.assertIsNone(rev.baserevisionsize)
497 self.assertEqual(rev.revision, fulltext)
497 self.assertEqual(rev.revision, fulltext)
498 self.assertIsNone(rev.delta)
498 self.assertIsNone(rev.delta)
499
499
500 with self.assertRaises(StopIteration):
500 with self.assertRaises(StopIteration):
501 next(gen)
501 next(gen)
502
502
503 # Emitting an unknown node after a known revision results in error.
503 # Emitting an unknown node after a known revision results in error.
504 with self.assertRaises(error.LookupError):
504 with self.assertRaises(error.LookupError):
505 list(f.emitrevisions([node, b'\x01' * 20]))
505 list(f.emitrevisions([node, b'\x01' * 20]))
506
506
507 def testmultiplerevisions(self):
507 def testmultiplerevisions(self):
508 fulltext0 = b'x' * 1024
508 fulltext0 = b'x' * 1024
509 fulltext1 = fulltext0 + b'y'
509 fulltext1 = fulltext0 + b'y'
510 fulltext2 = b'y' + fulltext0 + b'z'
510 fulltext2 = b'y' + fulltext0 + b'z'
511
511
512 f = self._makefilefn()
512 f = self._makefilefn()
513 with self._maketransactionfn() as tr:
513 with self._maketransactionfn() as tr:
514 node0 = f.add(fulltext0, None, tr, 0, nullid, nullid)
514 node0 = f.add(fulltext0, None, tr, 0, nullid, nullid)
515 node1 = f.add(fulltext1, None, tr, 1, node0, nullid)
515 node1 = f.add(fulltext1, None, tr, 1, node0, nullid)
516 node2 = f.add(fulltext2, None, tr, 3, node1, nullid)
516 node2 = f.add(fulltext2, None, tr, 3, node1, nullid)
517
517
518 self.assertEqual(f.storageinfo(), {})
518 self.assertEqual(f.storageinfo(), {})
519 self.assertEqual(
519 self.assertEqual(
520 f.storageinfo(revisionscount=True, trackedsize=True),
520 f.storageinfo(revisionscount=True, trackedsize=True),
521 {
521 {
522 'revisionscount': 3,
522 'revisionscount': 3,
523 'trackedsize': len(fulltext0) + len(fulltext1) + len(fulltext2),
523 'trackedsize': len(fulltext0) + len(fulltext1) + len(fulltext2),
524 })
524 })
525
525
526 self.assertEqual(f.size(0), len(fulltext0))
526 self.assertEqual(f.size(0), len(fulltext0))
527 self.assertEqual(f.size(1), len(fulltext1))
527 self.assertEqual(f.size(1), len(fulltext1))
528 self.assertEqual(f.size(2), len(fulltext2))
528 self.assertEqual(f.size(2), len(fulltext2))
529
529
530 with self.assertRaises(IndexError):
530 with self.assertRaises(IndexError):
531 f.size(3)
531 f.size(3)
532
532
533 self.assertEqual(f.revision(node0), fulltext0)
533 self.assertEqual(f.revision(node0), fulltext0)
534 self.assertEqual(f.revision(node0, raw=True), fulltext0)
534 self.assertEqual(f.revision(node0, raw=True), fulltext0)
535 self.assertEqual(f.revision(node1), fulltext1)
535 self.assertEqual(f.revision(node1), fulltext1)
536 self.assertEqual(f.revision(node1, raw=True), fulltext1)
536 self.assertEqual(f.revision(node1, raw=True), fulltext1)
537 self.assertEqual(f.revision(node2), fulltext2)
537 self.assertEqual(f.revision(node2), fulltext2)
538 self.assertEqual(f.revision(node2, raw=True), fulltext2)
538 self.assertEqual(f.revision(node2, raw=True), fulltext2)
539
539
540 with self.assertRaises(error.LookupError):
540 with self.assertRaises(error.LookupError):
541 f.revision(b'\x01' * 20)
541 f.revision(b'\x01' * 20)
542
542
543 self.assertEqual(f.read(node0), fulltext0)
543 self.assertEqual(f.read(node0), fulltext0)
544 self.assertEqual(f.read(node1), fulltext1)
544 self.assertEqual(f.read(node1), fulltext1)
545 self.assertEqual(f.read(node2), fulltext2)
545 self.assertEqual(f.read(node2), fulltext2)
546
546
547 with self.assertRaises(error.LookupError):
547 with self.assertRaises(error.LookupError):
548 f.read(b'\x01' * 20)
548 f.read(b'\x01' * 20)
549
549
550 self.assertFalse(f.renamed(node0))
550 self.assertFalse(f.renamed(node0))
551 self.assertFalse(f.renamed(node1))
551 self.assertFalse(f.renamed(node1))
552 self.assertFalse(f.renamed(node2))
552 self.assertFalse(f.renamed(node2))
553
553
554 with self.assertRaises(error.LookupError):
554 with self.assertRaises(error.LookupError):
555 f.renamed(b'\x01' * 20)
555 f.renamed(b'\x01' * 20)
556
556
557 self.assertFalse(f.cmp(node0, fulltext0))
557 self.assertFalse(f.cmp(node0, fulltext0))
558 self.assertFalse(f.cmp(node1, fulltext1))
558 self.assertFalse(f.cmp(node1, fulltext1))
559 self.assertFalse(f.cmp(node2, fulltext2))
559 self.assertFalse(f.cmp(node2, fulltext2))
560
560
561 self.assertTrue(f.cmp(node1, fulltext0))
561 self.assertTrue(f.cmp(node1, fulltext0))
562 self.assertTrue(f.cmp(node2, fulltext1))
562 self.assertTrue(f.cmp(node2, fulltext1))
563
563
564 with self.assertRaises(error.LookupError):
564 with self.assertRaises(error.LookupError):
565 f.cmp(b'\x01' * 20, b'irrelevant')
565 f.cmp(b'\x01' * 20, b'irrelevant')
566
566
567 # Nodes should be emitted in order.
567 # Nodes should be emitted in order.
568 gen = f.emitrevisions([node0, node1, node2], revisiondata=True)
568 gen = f.emitrevisions([node0, node1, node2], revisiondata=True)
569
569
570 rev = next(gen)
570 rev = next(gen)
571
571
572 self.assertEqual(rev.node, node0)
572 self.assertEqual(rev.node, node0)
573 self.assertEqual(rev.p1node, nullid)
573 self.assertEqual(rev.p1node, nullid)
574 self.assertEqual(rev.p2node, nullid)
574 self.assertEqual(rev.p2node, nullid)
575 self.assertIsNone(rev.linknode)
575 self.assertIsNone(rev.linknode)
576 self.assertEqual(rev.basenode, nullid)
576 self.assertEqual(rev.basenode, nullid)
577 self.assertIsNone(rev.baserevisionsize)
577 self.assertIsNone(rev.baserevisionsize)
578 self.assertEqual(rev.revision, fulltext0)
578 self.assertEqual(rev.revision, fulltext0)
579 self.assertIsNone(rev.delta)
579 self.assertIsNone(rev.delta)
580
580
581 rev = next(gen)
581 rev = next(gen)
582
582
583 self.assertEqual(rev.node, node1)
583 self.assertEqual(rev.node, node1)
584 self.assertEqual(rev.p1node, node0)
584 self.assertEqual(rev.p1node, node0)
585 self.assertEqual(rev.p2node, nullid)
585 self.assertEqual(rev.p2node, nullid)
586 self.assertIsNone(rev.linknode)
586 self.assertIsNone(rev.linknode)
587 self.assertEqual(rev.basenode, node0)
587 self.assertEqual(rev.basenode, node0)
588 self.assertIsNone(rev.baserevisionsize)
588 self.assertIsNone(rev.baserevisionsize)
589 self.assertIsNone(rev.revision)
589 self.assertIsNone(rev.revision)
590 self.assertEqual(rev.delta,
590 self.assertEqual(rev.delta,
591 b'\x00\x00\x00\x00\x00\x00\x04\x00\x00\x00\x04\x01' +
591 b'\x00\x00\x00\x00\x00\x00\x04\x00\x00\x00\x04\x01' +
592 fulltext1)
592 fulltext1)
593
593
594 rev = next(gen)
594 rev = next(gen)
595
595
596 self.assertEqual(rev.node, node2)
596 self.assertEqual(rev.node, node2)
597 self.assertEqual(rev.p1node, node1)
597 self.assertEqual(rev.p1node, node1)
598 self.assertEqual(rev.p2node, nullid)
598 self.assertEqual(rev.p2node, nullid)
599 self.assertIsNone(rev.linknode)
599 self.assertIsNone(rev.linknode)
600 self.assertEqual(rev.basenode, node1)
600 self.assertEqual(rev.basenode, node1)
601 self.assertIsNone(rev.baserevisionsize)
601 self.assertIsNone(rev.baserevisionsize)
602 self.assertIsNone(rev.revision)
602 self.assertIsNone(rev.revision)
603 self.assertEqual(rev.delta,
603 self.assertEqual(rev.delta,
604 b'\x00\x00\x00\x00\x00\x00\x04\x01\x00\x00\x04\x02' +
604 b'\x00\x00\x00\x00\x00\x00\x04\x01\x00\x00\x04\x02' +
605 fulltext2)
605 fulltext2)
606
606
607 with self.assertRaises(StopIteration):
607 with self.assertRaises(StopIteration):
608 next(gen)
608 next(gen)
609
609
610 # Request not in DAG order is reordered to be in DAG order.
610 # Request not in DAG order is reordered to be in DAG order.
611 gen = f.emitrevisions([node2, node1, node0], revisiondata=True)
611 gen = f.emitrevisions([node2, node1, node0], revisiondata=True)
612
612
613 rev = next(gen)
613 rev = next(gen)
614
614
615 self.assertEqual(rev.node, node0)
615 self.assertEqual(rev.node, node0)
616 self.assertEqual(rev.p1node, nullid)
616 self.assertEqual(rev.p1node, nullid)
617 self.assertEqual(rev.p2node, nullid)
617 self.assertEqual(rev.p2node, nullid)
618 self.assertIsNone(rev.linknode)
618 self.assertIsNone(rev.linknode)
619 self.assertEqual(rev.basenode, nullid)
619 self.assertEqual(rev.basenode, nullid)
620 self.assertIsNone(rev.baserevisionsize)
620 self.assertIsNone(rev.baserevisionsize)
621 self.assertEqual(rev.revision, fulltext0)
621 self.assertEqual(rev.revision, fulltext0)
622 self.assertIsNone(rev.delta)
622 self.assertIsNone(rev.delta)
623
623
624 rev = next(gen)
624 rev = next(gen)
625
625
626 self.assertEqual(rev.node, node1)
626 self.assertEqual(rev.node, node1)
627 self.assertEqual(rev.p1node, node0)
627 self.assertEqual(rev.p1node, node0)
628 self.assertEqual(rev.p2node, nullid)
628 self.assertEqual(rev.p2node, nullid)
629 self.assertIsNone(rev.linknode)
629 self.assertIsNone(rev.linknode)
630 self.assertEqual(rev.basenode, node0)
630 self.assertEqual(rev.basenode, node0)
631 self.assertIsNone(rev.baserevisionsize)
631 self.assertIsNone(rev.baserevisionsize)
632 self.assertIsNone(rev.revision)
632 self.assertIsNone(rev.revision)
633 self.assertEqual(rev.delta,
633 self.assertEqual(rev.delta,
634 b'\x00\x00\x00\x00\x00\x00\x04\x00\x00\x00\x04\x01' +
634 b'\x00\x00\x00\x00\x00\x00\x04\x00\x00\x00\x04\x01' +
635 fulltext1)
635 fulltext1)
636
636
637 rev = next(gen)
637 rev = next(gen)
638
638
639 self.assertEqual(rev.node, node2)
639 self.assertEqual(rev.node, node2)
640 self.assertEqual(rev.p1node, node1)
640 self.assertEqual(rev.p1node, node1)
641 self.assertEqual(rev.p2node, nullid)
641 self.assertEqual(rev.p2node, nullid)
642 self.assertIsNone(rev.linknode)
642 self.assertIsNone(rev.linknode)
643 self.assertEqual(rev.basenode, node1)
643 self.assertEqual(rev.basenode, node1)
644 self.assertIsNone(rev.baserevisionsize)
644 self.assertIsNone(rev.baserevisionsize)
645 self.assertIsNone(rev.revision)
645 self.assertIsNone(rev.revision)
646 self.assertEqual(rev.delta,
646 self.assertEqual(rev.delta,
647 b'\x00\x00\x00\x00\x00\x00\x04\x01\x00\x00\x04\x02' +
647 b'\x00\x00\x00\x00\x00\x00\x04\x01\x00\x00\x04\x02' +
648 fulltext2)
648 fulltext2)
649
649
650 with self.assertRaises(StopIteration):
650 with self.assertRaises(StopIteration):
651 next(gen)
651 next(gen)
652
652
653 # Unrecognized nodesorder value raises ProgrammingError.
653 # Unrecognized nodesorder value raises ProgrammingError.
654 with self.assertRaises(error.ProgrammingError):
654 with self.assertRaises(error.ProgrammingError):
655 list(f.emitrevisions([], nodesorder='bad'))
655 list(f.emitrevisions([], nodesorder='bad'))
656
656
657 # nodesorder=storage is recognized. But we can't test it thoroughly
657 # nodesorder=storage is recognized. But we can't test it thoroughly
658 # because behavior is storage-dependent.
658 # because behavior is storage-dependent.
659 res = list(f.emitrevisions([node2, node1, node0],
659 res = list(f.emitrevisions([node2, node1, node0],
660 nodesorder='storage'))
660 nodesorder='storage'))
661 self.assertEqual(len(res), 3)
661 self.assertEqual(len(res), 3)
662 self.assertEqual({o.node for o in res}, {node0, node1, node2})
662 self.assertEqual({o.node for o in res}, {node0, node1, node2})
663
663
664 # nodesorder=nodes forces the order.
664 # nodesorder=nodes forces the order.
665 gen = f.emitrevisions([node2, node0], nodesorder='nodes',
665 gen = f.emitrevisions([node2, node0], nodesorder='nodes',
666 revisiondata=True)
666 revisiondata=True)
667
667
668 rev = next(gen)
668 rev = next(gen)
669 self.assertEqual(rev.node, node2)
669 self.assertEqual(rev.node, node2)
670 self.assertEqual(rev.p1node, node1)
670 self.assertEqual(rev.p1node, node1)
671 self.assertEqual(rev.p2node, nullid)
671 self.assertEqual(rev.p2node, nullid)
672 self.assertEqual(rev.basenode, nullid)
672 self.assertEqual(rev.basenode, nullid)
673 self.assertIsNone(rev.baserevisionsize)
673 self.assertIsNone(rev.baserevisionsize)
674 self.assertEqual(rev.revision, fulltext2)
674 self.assertEqual(rev.revision, fulltext2)
675 self.assertIsNone(rev.delta)
675 self.assertIsNone(rev.delta)
676
676
677 rev = next(gen)
677 rev = next(gen)
678 self.assertEqual(rev.node, node0)
678 self.assertEqual(rev.node, node0)
679 self.assertEqual(rev.p1node, nullid)
679 self.assertEqual(rev.p1node, nullid)
680 self.assertEqual(rev.p2node, nullid)
680 self.assertEqual(rev.p2node, nullid)
681 # Delta behavior is storage dependent, so we can't easily test it.
681 # Delta behavior is storage dependent, so we can't easily test it.
682
682
683 with self.assertRaises(StopIteration):
683 with self.assertRaises(StopIteration):
684 next(gen)
684 next(gen)
685
685
686 # assumehaveparentrevisions=False (the default) won't send a delta for
686 # assumehaveparentrevisions=False (the default) won't send a delta for
687 # the first revision.
687 # the first revision.
688 gen = f.emitrevisions({node2, node1}, revisiondata=True)
688 gen = f.emitrevisions({node2, node1}, revisiondata=True)
689
689
690 rev = next(gen)
690 rev = next(gen)
691 self.assertEqual(rev.node, node1)
691 self.assertEqual(rev.node, node1)
692 self.assertEqual(rev.p1node, node0)
692 self.assertEqual(rev.p1node, node0)
693 self.assertEqual(rev.p2node, nullid)
693 self.assertEqual(rev.p2node, nullid)
694 self.assertEqual(rev.basenode, nullid)
694 self.assertEqual(rev.basenode, nullid)
695 self.assertIsNone(rev.baserevisionsize)
695 self.assertIsNone(rev.baserevisionsize)
696 self.assertEqual(rev.revision, fulltext1)
696 self.assertEqual(rev.revision, fulltext1)
697 self.assertIsNone(rev.delta)
697 self.assertIsNone(rev.delta)
698
698
699 rev = next(gen)
699 rev = next(gen)
700 self.assertEqual(rev.node, node2)
700 self.assertEqual(rev.node, node2)
701 self.assertEqual(rev.p1node, node1)
701 self.assertEqual(rev.p1node, node1)
702 self.assertEqual(rev.p2node, nullid)
702 self.assertEqual(rev.p2node, nullid)
703 self.assertEqual(rev.basenode, node1)
703 self.assertEqual(rev.basenode, node1)
704 self.assertIsNone(rev.baserevisionsize)
704 self.assertIsNone(rev.baserevisionsize)
705 self.assertIsNone(rev.revision)
705 self.assertIsNone(rev.revision)
706 self.assertEqual(rev.delta,
706 self.assertEqual(rev.delta,
707 b'\x00\x00\x00\x00\x00\x00\x04\x01\x00\x00\x04\x02' +
707 b'\x00\x00\x00\x00\x00\x00\x04\x01\x00\x00\x04\x02' +
708 fulltext2)
708 fulltext2)
709
709
710 with self.assertRaises(StopIteration):
710 with self.assertRaises(StopIteration):
711 next(gen)
711 next(gen)
712
712
713 # assumehaveparentrevisions=True allows delta against initial revision.
713 # assumehaveparentrevisions=True allows delta against initial revision.
714 gen = f.emitrevisions([node2, node1],
714 gen = f.emitrevisions([node2, node1],
715 revisiondata=True, assumehaveparentrevisions=True)
715 revisiondata=True, assumehaveparentrevisions=True)
716
716
717 rev = next(gen)
717 rev = next(gen)
718 self.assertEqual(rev.node, node1)
718 self.assertEqual(rev.node, node1)
719 self.assertEqual(rev.p1node, node0)
719 self.assertEqual(rev.p1node, node0)
720 self.assertEqual(rev.p2node, nullid)
720 self.assertEqual(rev.p2node, nullid)
721 self.assertEqual(rev.basenode, node0)
721 self.assertEqual(rev.basenode, node0)
722 self.assertIsNone(rev.baserevisionsize)
722 self.assertIsNone(rev.baserevisionsize)
723 self.assertIsNone(rev.revision)
723 self.assertIsNone(rev.revision)
724 self.assertEqual(rev.delta,
724 self.assertEqual(rev.delta,
725 b'\x00\x00\x00\x00\x00\x00\x04\x00\x00\x00\x04\x01' +
725 b'\x00\x00\x00\x00\x00\x00\x04\x00\x00\x00\x04\x01' +
726 fulltext1)
726 fulltext1)
727
727
728 # forceprevious=True forces a delta against the previous revision.
728 # forceprevious=True forces a delta against the previous revision.
729 # Special case for initial revision.
729 # Special case for initial revision.
730 gen = f.emitrevisions([node0], revisiondata=True, deltaprevious=True)
730 gen = f.emitrevisions([node0], revisiondata=True, deltaprevious=True)
731
731
732 rev = next(gen)
732 rev = next(gen)
733 self.assertEqual(rev.node, node0)
733 self.assertEqual(rev.node, node0)
734 self.assertEqual(rev.p1node, nullid)
734 self.assertEqual(rev.p1node, nullid)
735 self.assertEqual(rev.p2node, nullid)
735 self.assertEqual(rev.p2node, nullid)
736 self.assertEqual(rev.basenode, nullid)
736 self.assertEqual(rev.basenode, nullid)
737 self.assertIsNone(rev.baserevisionsize)
737 self.assertIsNone(rev.baserevisionsize)
738 self.assertIsNone(rev.revision)
738 self.assertIsNone(rev.revision)
739 self.assertEqual(rev.delta,
739 self.assertEqual(rev.delta,
740 b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x04\x00' +
740 b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x04\x00' +
741 fulltext0)
741 fulltext0)
742
742
743 with self.assertRaises(StopIteration):
743 with self.assertRaises(StopIteration):
744 next(gen)
744 next(gen)
745
745
746 gen = f.emitrevisions([node0, node2], revisiondata=True,
746 gen = f.emitrevisions([node0, node2], revisiondata=True,
747 deltaprevious=True)
747 deltaprevious=True)
748
748
749 rev = next(gen)
749 rev = next(gen)
750 self.assertEqual(rev.node, node0)
750 self.assertEqual(rev.node, node0)
751 self.assertEqual(rev.p1node, nullid)
751 self.assertEqual(rev.p1node, nullid)
752 self.assertEqual(rev.p2node, nullid)
752 self.assertEqual(rev.p2node, nullid)
753 self.assertEqual(rev.basenode, nullid)
753 self.assertEqual(rev.basenode, nullid)
754 self.assertIsNone(rev.baserevisionsize)
754 self.assertIsNone(rev.baserevisionsize)
755 self.assertIsNone(rev.revision)
755 self.assertIsNone(rev.revision)
756 self.assertEqual(rev.delta,
756 self.assertEqual(rev.delta,
757 b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x04\x00' +
757 b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x04\x00' +
758 fulltext0)
758 fulltext0)
759
759
760 rev = next(gen)
760 rev = next(gen)
761 self.assertEqual(rev.node, node2)
761 self.assertEqual(rev.node, node2)
762 self.assertEqual(rev.p1node, node1)
762 self.assertEqual(rev.p1node, node1)
763 self.assertEqual(rev.p2node, nullid)
763 self.assertEqual(rev.p2node, nullid)
764 self.assertEqual(rev.basenode, node0)
764 self.assertEqual(rev.basenode, node0)
765
765
766 with self.assertRaises(StopIteration):
766 with self.assertRaises(StopIteration):
767 next(gen)
767 next(gen)
768
768
769 def testrenamed(self):
769 def testrenamed(self):
770 fulltext0 = b'foo'
770 fulltext0 = b'foo'
771 fulltext1 = b'bar'
771 fulltext1 = b'bar'
772 fulltext2 = b'baz'
772 fulltext2 = b'baz'
773
773
774 meta1 = {
774 meta1 = {
775 b'copy': b'source0',
775 b'copy': b'source0',
776 b'copyrev': b'a' * 40,
776 b'copyrev': b'a' * 40,
777 }
777 }
778
778
779 meta2 = {
779 meta2 = {
780 b'copy': b'source1',
780 b'copy': b'source1',
781 b'copyrev': b'b' * 40,
781 b'copyrev': b'b' * 40,
782 }
782 }
783
783
784 stored1 = b''.join([
784 stored1 = b''.join([
785 b'\x01\ncopy: source0\n',
785 b'\x01\ncopy: source0\n',
786 b'copyrev: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\n\x01\n',
786 b'copyrev: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\n\x01\n',
787 fulltext1,
787 fulltext1,
788 ])
788 ])
789
789
790 stored2 = b''.join([
790 stored2 = b''.join([
791 b'\x01\ncopy: source1\n',
791 b'\x01\ncopy: source1\n',
792 b'copyrev: bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb\n\x01\n',
792 b'copyrev: bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb\n\x01\n',
793 fulltext2,
793 fulltext2,
794 ])
794 ])
795
795
796 f = self._makefilefn()
796 f = self._makefilefn()
797 with self._maketransactionfn() as tr:
797 with self._maketransactionfn() as tr:
798 node0 = f.add(fulltext0, None, tr, 0, nullid, nullid)
798 node0 = f.add(fulltext0, None, tr, 0, nullid, nullid)
799 node1 = f.add(fulltext1, meta1, tr, 1, node0, nullid)
799 node1 = f.add(fulltext1, meta1, tr, 1, node0, nullid)
800 node2 = f.add(fulltext2, meta2, tr, 2, nullid, nullid)
800 node2 = f.add(fulltext2, meta2, tr, 2, nullid, nullid)
801
801
802 # Metadata header isn't recognized when parent isn't nullid.
802 # Metadata header isn't recognized when parent isn't nullid.
803 self.assertEqual(f.size(1), len(stored1))
803 self.assertEqual(f.size(1), len(stored1))
804 self.assertEqual(f.size(2), len(fulltext2))
804 self.assertEqual(f.size(2), len(fulltext2))
805
805
806 self.assertEqual(f.revision(node1), stored1)
806 self.assertEqual(f.revision(node1), stored1)
807 self.assertEqual(f.revision(node1, raw=True), stored1)
807 self.assertEqual(f.revision(node1, raw=True), stored1)
808 self.assertEqual(f.revision(node2), stored2)
808 self.assertEqual(f.revision(node2), stored2)
809 self.assertEqual(f.revision(node2, raw=True), stored2)
809 self.assertEqual(f.revision(node2, raw=True), stored2)
810
810
811 self.assertEqual(f.read(node1), fulltext1)
811 self.assertEqual(f.read(node1), fulltext1)
812 self.assertEqual(f.read(node2), fulltext2)
812 self.assertEqual(f.read(node2), fulltext2)
813
813
814 # Returns False when first parent is set.
814 # Returns False when first parent is set.
815 self.assertFalse(f.renamed(node1))
815 self.assertFalse(f.renamed(node1))
816 self.assertEqual(f.renamed(node2), (b'source1', b'\xbb' * 20))
816 self.assertEqual(f.renamed(node2), (b'source1', b'\xbb' * 20))
817
817
818 self.assertTrue(f.cmp(node1, fulltext1))
818 self.assertTrue(f.cmp(node1, fulltext1))
819 self.assertTrue(f.cmp(node1, stored1))
819 self.assertTrue(f.cmp(node1, stored1))
820 self.assertFalse(f.cmp(node2, fulltext2))
820 self.assertFalse(f.cmp(node2, fulltext2))
821 self.assertTrue(f.cmp(node2, stored2))
821 self.assertTrue(f.cmp(node2, stored2))
822
822
823 def testmetadataprefix(self):
823 def testmetadataprefix(self):
824 # Content with metadata prefix has extra prefix inserted in storage.
824 # Content with metadata prefix has extra prefix inserted in storage.
825 fulltext0 = b'\x01\nfoo'
825 fulltext0 = b'\x01\nfoo'
826 stored0 = b'\x01\n\x01\n\x01\nfoo'
826 stored0 = b'\x01\n\x01\n\x01\nfoo'
827
827
828 fulltext1 = b'\x01\nbar'
828 fulltext1 = b'\x01\nbar'
829 meta1 = {
829 meta1 = {
830 b'copy': b'source0',
830 b'copy': b'source0',
831 b'copyrev': b'b' * 40,
831 b'copyrev': b'b' * 40,
832 }
832 }
833 stored1 = b''.join([
833 stored1 = b''.join([
834 b'\x01\ncopy: source0\n',
834 b'\x01\ncopy: source0\n',
835 b'copyrev: %s\n' % (b'b' * 40),
835 b'copyrev: %s\n' % (b'b' * 40),
836 b'\x01\n\x01\nbar',
836 b'\x01\n\x01\nbar',
837 ])
837 ])
838
838
839 f = self._makefilefn()
839 f = self._makefilefn()
840 with self._maketransactionfn() as tr:
840 with self._maketransactionfn() as tr:
841 node0 = f.add(fulltext0, {}, tr, 0, nullid, nullid)
841 node0 = f.add(fulltext0, {}, tr, 0, nullid, nullid)
842 node1 = f.add(fulltext1, meta1, tr, 1, nullid, nullid)
842 node1 = f.add(fulltext1, meta1, tr, 1, nullid, nullid)
843
843
844 # TODO this is buggy.
844 # TODO this is buggy.
845 self.assertEqual(f.size(0), len(fulltext0) + 4)
845 self.assertEqual(f.size(0), len(fulltext0) + 4)
846
846
847 self.assertEqual(f.size(1), len(fulltext1))
847 self.assertEqual(f.size(1), len(fulltext1))
848
848
849 self.assertEqual(f.revision(node0), stored0)
849 self.assertEqual(f.revision(node0), stored0)
850 self.assertEqual(f.revision(node0, raw=True), stored0)
850 self.assertEqual(f.revision(node0, raw=True), stored0)
851
851
852 self.assertEqual(f.revision(node1), stored1)
852 self.assertEqual(f.revision(node1), stored1)
853 self.assertEqual(f.revision(node1, raw=True), stored1)
853 self.assertEqual(f.revision(node1, raw=True), stored1)
854
854
855 self.assertEqual(f.read(node0), fulltext0)
855 self.assertEqual(f.read(node0), fulltext0)
856 self.assertEqual(f.read(node1), fulltext1)
856 self.assertEqual(f.read(node1), fulltext1)
857
857
858 self.assertFalse(f.cmp(node0, fulltext0))
858 self.assertFalse(f.cmp(node0, fulltext0))
859 self.assertTrue(f.cmp(node0, stored0))
859 self.assertTrue(f.cmp(node0, stored0))
860
860
861 self.assertFalse(f.cmp(node1, fulltext1))
861 self.assertFalse(f.cmp(node1, fulltext1))
862 self.assertTrue(f.cmp(node1, stored0))
862 self.assertTrue(f.cmp(node1, stored0))
863
863
864 def testbadnoderead(self):
864 def testbadnoderead(self):
865 f = self._makefilefn()
865 f = self._makefilefn()
866
866
867 fulltext0 = b'foo\n' * 30
867 fulltext0 = b'foo\n' * 30
868 fulltext1 = fulltext0 + b'bar\n'
868 fulltext1 = fulltext0 + b'bar\n'
869
869
870 with self._maketransactionfn() as tr:
870 with self._maketransactionfn() as tr:
871 node0 = f.add(fulltext0, None, tr, 0, nullid, nullid)
871 node0 = f.add(fulltext0, None, tr, 0, nullid, nullid)
872 node1 = b'\xaa' * 20
872 node1 = b'\xaa' * 20
873
873
874 self._addrawrevisionfn(f, tr, node1, node0, nullid, 1,
874 self._addrawrevisionfn(f, tr, node1, node0, nullid, 1,
875 rawtext=fulltext1)
875 rawtext=fulltext1)
876
876
877 self.assertEqual(len(f), 2)
877 self.assertEqual(len(f), 2)
878 self.assertEqual(f.parents(node1), (node0, nullid))
878 self.assertEqual(f.parents(node1), (node0, nullid))
879
879
880 # revision() raises since it performs hash verification.
880 # revision() raises since it performs hash verification.
881 with self.assertRaises(error.StorageError):
881 with self.assertRaises(error.StorageError):
882 f.revision(node1)
882 f.revision(node1)
883
883
884 # raw=True still verifies because there are no special storage
884 # raw=True still verifies because there are no special storage
885 # settings.
885 # settings.
886 with self.assertRaises(error.StorageError):
886 with self.assertRaises(error.StorageError):
887 f.revision(node1, raw=True)
887 f.revision(node1, raw=True)
888
888
889 # read() behaves like revision().
889 # read() behaves like revision().
890 with self.assertRaises(error.StorageError):
890 with self.assertRaises(error.StorageError):
891 f.read(node1)
891 f.read(node1)
892
892
893 # We can't test renamed() here because some backends may not require
893 # We can't test renamed() here because some backends may not require
894 # reading/validating the fulltext to return rename metadata.
894 # reading/validating the fulltext to return rename metadata.
895
895
896 def testbadnoderevisionraw(self):
896 def testbadnoderevisionraw(self):
897 # Like above except we test revision(raw=True) first to isolate
897 # Like above except we test revision(raw=True) first to isolate
898 # revision caching behavior.
898 # revision caching behavior.
899 f = self._makefilefn()
899 f = self._makefilefn()
900
900
901 fulltext0 = b'foo\n' * 30
901 fulltext0 = b'foo\n' * 30
902 fulltext1 = fulltext0 + b'bar\n'
902 fulltext1 = fulltext0 + b'bar\n'
903
903
904 with self._maketransactionfn() as tr:
904 with self._maketransactionfn() as tr:
905 node0 = f.add(fulltext0, None, tr, 0, nullid, nullid)
905 node0 = f.add(fulltext0, None, tr, 0, nullid, nullid)
906 node1 = b'\xaa' * 20
906 node1 = b'\xaa' * 20
907
907
908 self._addrawrevisionfn(f, tr, node1, node0, nullid, 1,
908 self._addrawrevisionfn(f, tr, node1, node0, nullid, 1,
909 rawtext=fulltext1)
909 rawtext=fulltext1)
910
910
911 with self.assertRaises(error.StorageError):
911 with self.assertRaises(error.StorageError):
912 f.revision(node1, raw=True)
912 f.revision(node1, raw=True)
913
913
914 with self.assertRaises(error.StorageError):
914 with self.assertRaises(error.StorageError):
915 f.revision(node1, raw=True)
915 f.revision(node1, raw=True)
916
916
917 def testbadnoderevisionraw(self):
917 def testbadnoderevisionraw(self):
918 # Like above except we test read() first to isolate revision caching
918 # Like above except we test read() first to isolate revision caching
919 # behavior.
919 # behavior.
920 f = self._makefilefn()
920 f = self._makefilefn()
921
921
922 fulltext0 = b'foo\n' * 30
922 fulltext0 = b'foo\n' * 30
923 fulltext1 = fulltext0 + b'bar\n'
923 fulltext1 = fulltext0 + b'bar\n'
924
924
925 with self._maketransactionfn() as tr:
925 with self._maketransactionfn() as tr:
926 node0 = f.add(fulltext0, None, tr, 0, nullid, nullid)
926 node0 = f.add(fulltext0, None, tr, 0, nullid, nullid)
927 node1 = b'\xaa' * 20
927 node1 = b'\xaa' * 20
928
928
929 self._addrawrevisionfn(f, tr, node1, node0, nullid, 1,
929 self._addrawrevisionfn(f, tr, node1, node0, nullid, 1,
930 rawtext=fulltext1)
930 rawtext=fulltext1)
931
931
932 with self.assertRaises(error.StorageError):
932 with self.assertRaises(error.StorageError):
933 f.read(node1)
933 f.read(node1)
934
934
935 with self.assertRaises(error.StorageError):
935 with self.assertRaises(error.StorageError):
936 f.read(node1)
936 f.read(node1)
937
937
938 def testbadnodedelta(self):
938 def testbadnodedelta(self):
939 f = self._makefilefn()
939 f = self._makefilefn()
940
940
941 fulltext0 = b'foo\n' * 31
941 fulltext0 = b'foo\n' * 31
942 fulltext1 = fulltext0 + b'bar\n'
942 fulltext1 = fulltext0 + b'bar\n'
943 fulltext2 = fulltext1 + b'baz\n'
943 fulltext2 = fulltext1 + b'baz\n'
944
944
945 with self._maketransactionfn() as tr:
945 with self._maketransactionfn() as tr:
946 node0 = f.add(fulltext0, None, tr, 0, nullid, nullid)
946 node0 = f.add(fulltext0, None, tr, 0, nullid, nullid)
947 node1 = b'\xaa' * 20
947 node1 = b'\xaa' * 20
948
948
949 self._addrawrevisionfn(f, tr, node1, node0, nullid, 1,
949 self._addrawrevisionfn(f, tr, node1, node0, nullid, 1,
950 rawtext=fulltext1)
950 rawtext=fulltext1)
951
951
952 with self.assertRaises(error.StorageError):
952 with self.assertRaises(error.StorageError):
953 f.read(node1)
953 f.read(node1)
954
954
955 diff = mdiff.textdiff(fulltext1, fulltext2)
956 node2 = storageutil.hashrevisionsha1(fulltext2, node1, nullid)
955 node2 = storageutil.hashrevisionsha1(fulltext2, node1, nullid)
957 deltas = [(node2, node1, nullid, b'\x01' * 20, node1, diff, 0)]
958
956
959 # This /might/ fail on some backends.
960 with self._maketransactionfn() as tr:
957 with self._maketransactionfn() as tr:
961 f.addgroup(deltas, lambda x: 0, tr)
958 delta = mdiff.textdiff(fulltext1, fulltext2)
959 self._addrawrevisionfn(f, tr, node2, node1, nullid,
960 2, delta=(1, delta))
962
961
963 self.assertEqual(len(f), 3)
962 self.assertEqual(len(f), 3)
964
963
965 # Assuming a delta is stored, we shouldn't need to validate node1 in
964 # Assuming a delta is stored, we shouldn't need to validate node1 in
966 # order to retrieve node2.
965 # order to retrieve node2.
967 self.assertEqual(f.read(node2), fulltext2)
966 self.assertEqual(f.read(node2), fulltext2)
968
967
969 def testcensored(self):
968 def testcensored(self):
970 f = self._makefilefn()
969 f = self._makefilefn()
971
970
972 stored1 = storageutil.packmeta({
971 stored1 = storageutil.packmeta({
973 b'censored': b'tombstone',
972 b'censored': b'tombstone',
974 }, b'')
973 }, b'')
975
974
976 with self._maketransactionfn() as tr:
975 with self._maketransactionfn() as tr:
977 node0 = f.add(b'foo', None, tr, 0, nullid, nullid)
976 node0 = f.add(b'foo', None, tr, 0, nullid, nullid)
978
977
979 # The node value doesn't matter since we can't verify it.
978 # The node value doesn't matter since we can't verify it.
980 node1 = b'\xbb' * 20
979 node1 = b'\xbb' * 20
981
980
982 self._addrawrevisionfn(f, tr, node1, node0, nullid, 1, stored1,
981 self._addrawrevisionfn(f, tr, node1, node0, nullid, 1, stored1,
983 censored=True)
982 censored=True)
984
983
985 self.assertTrue(f.iscensored(1))
984 self.assertTrue(f.iscensored(1))
986
985
987 with self.assertRaises(error.CensoredNodeError):
986 with self.assertRaises(error.CensoredNodeError):
988 f.revision(1)
987 f.revision(1)
989
988
990 with self.assertRaises(error.CensoredNodeError):
989 with self.assertRaises(error.CensoredNodeError):
991 f.revision(1, raw=True)
990 f.revision(1, raw=True)
992
991
993 with self.assertRaises(error.CensoredNodeError):
992 with self.assertRaises(error.CensoredNodeError):
994 f.read(1)
993 f.read(1)
995
994
996 def testcensoredrawrevision(self):
995 def testcensoredrawrevision(self):
997 # Like above, except we do the revision(raw=True) request first to
996 # Like above, except we do the revision(raw=True) request first to
998 # isolate revision caching behavior.
997 # isolate revision caching behavior.
999
998
1000 f = self._makefilefn()
999 f = self._makefilefn()
1001
1000
1002 stored1 = storageutil.packmeta({
1001 stored1 = storageutil.packmeta({
1003 b'censored': b'tombstone',
1002 b'censored': b'tombstone',
1004 }, b'')
1003 }, b'')
1005
1004
1006 with self._maketransactionfn() as tr:
1005 with self._maketransactionfn() as tr:
1007 node0 = f.add(b'foo', None, tr, 0, nullid, nullid)
1006 node0 = f.add(b'foo', None, tr, 0, nullid, nullid)
1008
1007
1009 # The node value doesn't matter since we can't verify it.
1008 # The node value doesn't matter since we can't verify it.
1010 node1 = b'\xbb' * 20
1009 node1 = b'\xbb' * 20
1011
1010
1012 self._addrawrevisionfn(f, tr, node1, node0, nullid, 1, stored1,
1011 self._addrawrevisionfn(f, tr, node1, node0, nullid, 1, stored1,
1013 censored=True)
1012 censored=True)
1014
1013
1015 with self.assertRaises(error.CensoredNodeError):
1014 with self.assertRaises(error.CensoredNodeError):
1016 f.revision(1, raw=True)
1015 f.revision(1, raw=True)
1017
1016
1018 class ifilemutationtests(basetestcase):
1017 class ifilemutationtests(basetestcase):
1019 """Generic tests for the ifilemutation interface.
1018 """Generic tests for the ifilemutation interface.
1020
1019
1021 All file storage backends that support writing should conform to this
1020 All file storage backends that support writing should conform to this
1022 interface.
1021 interface.
1023
1022
1024 Use ``makeifilemutationtests()`` to create an instance of this type.
1023 Use ``makeifilemutationtests()`` to create an instance of this type.
1025 """
1024 """
1026 def testaddnoop(self):
1025 def testaddnoop(self):
1027 f = self._makefilefn()
1026 f = self._makefilefn()
1028 with self._maketransactionfn() as tr:
1027 with self._maketransactionfn() as tr:
1029 node0 = f.add(b'foo', None, tr, 0, nullid, nullid)
1028 node0 = f.add(b'foo', None, tr, 0, nullid, nullid)
1030 node1 = f.add(b'foo', None, tr, 0, nullid, nullid)
1029 node1 = f.add(b'foo', None, tr, 0, nullid, nullid)
1031 # Varying by linkrev shouldn't impact hash.
1030 # Varying by linkrev shouldn't impact hash.
1032 node2 = f.add(b'foo', None, tr, 1, nullid, nullid)
1031 node2 = f.add(b'foo', None, tr, 1, nullid, nullid)
1033
1032
1034 self.assertEqual(node1, node0)
1033 self.assertEqual(node1, node0)
1035 self.assertEqual(node2, node0)
1034 self.assertEqual(node2, node0)
1036 self.assertEqual(len(f), 1)
1035 self.assertEqual(len(f), 1)
1037
1036
1038 def testaddrevisionbadnode(self):
1037 def testaddrevisionbadnode(self):
1039 f = self._makefilefn()
1038 f = self._makefilefn()
1040 with self._maketransactionfn() as tr:
1039 with self._maketransactionfn() as tr:
1041 # Adding a revision with bad node value fails.
1040 # Adding a revision with bad node value fails.
1042 with self.assertRaises(error.StorageError):
1041 with self.assertRaises(error.StorageError):
1043 f.addrevision(b'foo', tr, 0, nullid, nullid, node=b'\x01' * 20)
1042 f.addrevision(b'foo', tr, 0, nullid, nullid, node=b'\x01' * 20)
1044
1043
1045 def testaddrevisionunknownflag(self):
1044 def testaddrevisionunknownflag(self):
1046 f = self._makefilefn()
1045 f = self._makefilefn()
1047 with self._maketransactionfn() as tr:
1046 with self._maketransactionfn() as tr:
1048 for i in range(15, 0, -1):
1047 for i in range(15, 0, -1):
1049 if (1 << i) & ~repository.REVISION_FLAGS_KNOWN:
1048 if (1 << i) & ~repository.REVISION_FLAGS_KNOWN:
1050 flags = 1 << i
1049 flags = 1 << i
1051 break
1050 break
1052
1051
1053 with self.assertRaises(error.StorageError):
1052 with self.assertRaises(error.StorageError):
1054 f.addrevision(b'foo', tr, 0, nullid, nullid, flags=flags)
1053 f.addrevision(b'foo', tr, 0, nullid, nullid, flags=flags)
1055
1054
1056 def testaddgroupsimple(self):
1055 def testaddgroupsimple(self):
1057 f = self._makefilefn()
1056 f = self._makefilefn()
1058
1057
1059 callbackargs = []
1058 callbackargs = []
1060 def cb(*args, **kwargs):
1059 def cb(*args, **kwargs):
1061 callbackargs.append((args, kwargs))
1060 callbackargs.append((args, kwargs))
1062
1061
1063 def linkmapper(node):
1062 def linkmapper(node):
1064 return 0
1063 return 0
1065
1064
1066 with self._maketransactionfn() as tr:
1065 with self._maketransactionfn() as tr:
1067 nodes = f.addgroup([], None, tr, addrevisioncb=cb)
1066 nodes = f.addgroup([], None, tr, addrevisioncb=cb)
1068
1067
1069 self.assertEqual(nodes, [])
1068 self.assertEqual(nodes, [])
1070 self.assertEqual(callbackargs, [])
1069 self.assertEqual(callbackargs, [])
1071 self.assertEqual(len(f), 0)
1070 self.assertEqual(len(f), 0)
1072
1071
1073 fulltext0 = b'foo'
1072 fulltext0 = b'foo'
1074 delta0 = mdiff.trivialdiffheader(len(fulltext0)) + fulltext0
1073 delta0 = mdiff.trivialdiffheader(len(fulltext0)) + fulltext0
1075
1074
1076 with self._maketransactionfn() as tr:
1075 with self._maketransactionfn() as tr:
1077 node0 = f.add(fulltext0, None, tr, 0, nullid, nullid)
1076 node0 = f.add(fulltext0, None, tr, 0, nullid, nullid)
1078
1077
1079 f = self._makefilefn()
1078 f = self._makefilefn()
1080
1079
1081 deltas = [
1080 deltas = [
1082 (node0, nullid, nullid, nullid, nullid, delta0, 0),
1081 (node0, nullid, nullid, nullid, nullid, delta0, 0),
1083 ]
1082 ]
1084
1083
1085 with self._maketransactionfn() as tr:
1084 with self._maketransactionfn() as tr:
1086 nodes = f.addgroup(deltas, linkmapper, tr, addrevisioncb=cb)
1085 nodes = f.addgroup(deltas, linkmapper, tr, addrevisioncb=cb)
1087
1086
1088 self.assertEqual(nodes, [
1087 self.assertEqual(nodes, [
1089 b'\x49\xd8\xcb\xb1\x5c\xe2\x57\x92\x04\x47'
1088 b'\x49\xd8\xcb\xb1\x5c\xe2\x57\x92\x04\x47'
1090 b'\x00\x6b\x46\x97\x8b\x7a\xf9\x80\xa9\x79'])
1089 b'\x00\x6b\x46\x97\x8b\x7a\xf9\x80\xa9\x79'])
1091
1090
1092 self.assertEqual(len(callbackargs), 1)
1091 self.assertEqual(len(callbackargs), 1)
1093 self.assertEqual(callbackargs[0][0][1], nodes[0])
1092 self.assertEqual(callbackargs[0][0][1], nodes[0])
1094
1093
1095 self.assertEqual(list(f.revs()), [0])
1094 self.assertEqual(list(f.revs()), [0])
1096 self.assertEqual(f.rev(nodes[0]), 0)
1095 self.assertEqual(f.rev(nodes[0]), 0)
1097 self.assertEqual(f.node(0), nodes[0])
1096 self.assertEqual(f.node(0), nodes[0])
1098
1097
1099 def testaddgroupmultiple(self):
1098 def testaddgroupmultiple(self):
1100 f = self._makefilefn()
1099 f = self._makefilefn()
1101
1100
1102 fulltexts = [
1101 fulltexts = [
1103 b'foo',
1102 b'foo',
1104 b'bar',
1103 b'bar',
1105 b'x' * 1024,
1104 b'x' * 1024,
1106 ]
1105 ]
1107
1106
1108 nodes = []
1107 nodes = []
1109 with self._maketransactionfn() as tr:
1108 with self._maketransactionfn() as tr:
1110 for fulltext in fulltexts:
1109 for fulltext in fulltexts:
1111 nodes.append(f.add(fulltext, None, tr, 0, nullid, nullid))
1110 nodes.append(f.add(fulltext, None, tr, 0, nullid, nullid))
1112
1111
1113 f = self._makefilefn()
1112 f = self._makefilefn()
1114 deltas = []
1113 deltas = []
1115 for i, fulltext in enumerate(fulltexts):
1114 for i, fulltext in enumerate(fulltexts):
1116 delta = mdiff.trivialdiffheader(len(fulltext)) + fulltext
1115 delta = mdiff.trivialdiffheader(len(fulltext)) + fulltext
1117
1116
1118 deltas.append((nodes[i], nullid, nullid, nullid, nullid, delta, 0))
1117 deltas.append((nodes[i], nullid, nullid, nullid, nullid, delta, 0))
1119
1118
1120 with self._maketransactionfn() as tr:
1119 with self._maketransactionfn() as tr:
1121 self.assertEqual(f.addgroup(deltas, lambda x: 0, tr), nodes)
1120 self.assertEqual(f.addgroup(deltas, lambda x: 0, tr), nodes)
1122
1121
1123 self.assertEqual(len(f), len(deltas))
1122 self.assertEqual(len(f), len(deltas))
1124 self.assertEqual(list(f.revs()), [0, 1, 2])
1123 self.assertEqual(list(f.revs()), [0, 1, 2])
1125 self.assertEqual(f.rev(nodes[0]), 0)
1124 self.assertEqual(f.rev(nodes[0]), 0)
1126 self.assertEqual(f.rev(nodes[1]), 1)
1125 self.assertEqual(f.rev(nodes[1]), 1)
1127 self.assertEqual(f.rev(nodes[2]), 2)
1126 self.assertEqual(f.rev(nodes[2]), 2)
1128 self.assertEqual(f.node(0), nodes[0])
1127 self.assertEqual(f.node(0), nodes[0])
1129 self.assertEqual(f.node(1), nodes[1])
1128 self.assertEqual(f.node(1), nodes[1])
1130 self.assertEqual(f.node(2), nodes[2])
1129 self.assertEqual(f.node(2), nodes[2])
1131
1130
1132 def testdeltaagainstcensored(self):
1131 def testdeltaagainstcensored(self):
1133 # Attempt to apply a delta made against a censored revision.
1132 # Attempt to apply a delta made against a censored revision.
1134 f = self._makefilefn()
1133 f = self._makefilefn()
1135
1134
1136 stored1 = storageutil.packmeta({
1135 stored1 = storageutil.packmeta({
1137 b'censored': b'tombstone',
1136 b'censored': b'tombstone',
1138 }, b'')
1137 }, b'')
1139
1138
1140 with self._maketransactionfn() as tr:
1139 with self._maketransactionfn() as tr:
1141 node0 = f.add(b'foo\n' * 30, None, tr, 0, nullid, nullid)
1140 node0 = f.add(b'foo\n' * 30, None, tr, 0, nullid, nullid)
1142
1141
1143 # The node value doesn't matter since we can't verify it.
1142 # The node value doesn't matter since we can't verify it.
1144 node1 = b'\xbb' * 20
1143 node1 = b'\xbb' * 20
1145
1144
1146 self._addrawrevisionfn(f, tr, node1, node0, nullid, 1, stored1,
1145 self._addrawrevisionfn(f, tr, node1, node0, nullid, 1, stored1,
1147 censored=True)
1146 censored=True)
1148
1147
1149 delta = mdiff.textdiff(b'bar\n' * 30, (b'bar\n' * 30) + b'baz\n')
1148 delta = mdiff.textdiff(b'bar\n' * 30, (b'bar\n' * 30) + b'baz\n')
1150 deltas = [(b'\xcc' * 20, node1, nullid, b'\x01' * 20, node1, delta, 0)]
1149 deltas = [(b'\xcc' * 20, node1, nullid, b'\x01' * 20, node1, delta, 0)]
1151
1150
1152 with self._maketransactionfn() as tr:
1151 with self._maketransactionfn() as tr:
1153 with self.assertRaises(error.CensoredBaseError):
1152 with self.assertRaises(error.CensoredBaseError):
1154 f.addgroup(deltas, lambda x: 0, tr)
1153 f.addgroup(deltas, lambda x: 0, tr)
1155
1154
1156 def testcensorrevisionbasic(self):
1155 def testcensorrevisionbasic(self):
1157 f = self._makefilefn()
1156 f = self._makefilefn()
1158
1157
1159 with self._maketransactionfn() as tr:
1158 with self._maketransactionfn() as tr:
1160 node0 = f.add(b'foo\n' * 30, None, tr, 0, nullid, nullid)
1159 node0 = f.add(b'foo\n' * 30, None, tr, 0, nullid, nullid)
1161 node1 = f.add(b'foo\n' * 31, None, tr, 1, node0, nullid)
1160 node1 = f.add(b'foo\n' * 31, None, tr, 1, node0, nullid)
1162 node2 = f.add(b'foo\n' * 32, None, tr, 2, node1, nullid)
1161 node2 = f.add(b'foo\n' * 32, None, tr, 2, node1, nullid)
1163
1162
1164 with self._maketransactionfn() as tr:
1163 with self._maketransactionfn() as tr:
1165 f.censorrevision(tr, node1)
1164 f.censorrevision(tr, node1)
1166
1165
1167 self.assertEqual(len(f), 3)
1166 self.assertEqual(len(f), 3)
1168 self.assertEqual(list(f.revs()), [0, 1, 2])
1167 self.assertEqual(list(f.revs()), [0, 1, 2])
1169
1168
1170 self.assertEqual(f.read(node0), b'foo\n' * 30)
1169 self.assertEqual(f.read(node0), b'foo\n' * 30)
1171 self.assertEqual(f.read(node2), b'foo\n' * 32)
1170 self.assertEqual(f.read(node2), b'foo\n' * 32)
1172
1171
1173 with self.assertRaises(error.CensoredNodeError):
1172 with self.assertRaises(error.CensoredNodeError):
1174 f.read(node1)
1173 f.read(node1)
1175
1174
1176 def testgetstrippointnoparents(self):
1175 def testgetstrippointnoparents(self):
1177 # N revisions where none have parents.
1176 # N revisions where none have parents.
1178 f = self._makefilefn()
1177 f = self._makefilefn()
1179
1178
1180 with self._maketransactionfn() as tr:
1179 with self._maketransactionfn() as tr:
1181 for rev in range(10):
1180 for rev in range(10):
1182 f.add(b'%d' % rev, None, tr, rev, nullid, nullid)
1181 f.add(b'%d' % rev, None, tr, rev, nullid, nullid)
1183
1182
1184 for rev in range(10):
1183 for rev in range(10):
1185 self.assertEqual(f.getstrippoint(rev), (rev, set()))
1184 self.assertEqual(f.getstrippoint(rev), (rev, set()))
1186
1185
1187 def testgetstrippointlinear(self):
1186 def testgetstrippointlinear(self):
1188 # N revisions in a linear chain.
1187 # N revisions in a linear chain.
1189 f = self._makefilefn()
1188 f = self._makefilefn()
1190
1189
1191 with self._maketransactionfn() as tr:
1190 with self._maketransactionfn() as tr:
1192 p1 = nullid
1191 p1 = nullid
1193
1192
1194 for rev in range(10):
1193 for rev in range(10):
1195 f.add(b'%d' % rev, None, tr, rev, p1, nullid)
1194 f.add(b'%d' % rev, None, tr, rev, p1, nullid)
1196
1195
1197 for rev in range(10):
1196 for rev in range(10):
1198 self.assertEqual(f.getstrippoint(rev), (rev, set()))
1197 self.assertEqual(f.getstrippoint(rev), (rev, set()))
1199
1198
1200 def testgetstrippointmultipleheads(self):
1199 def testgetstrippointmultipleheads(self):
1201 f = self._makefilefn()
1200 f = self._makefilefn()
1202
1201
1203 with self._maketransactionfn() as tr:
1202 with self._maketransactionfn() as tr:
1204 node0 = f.add(b'0', None, tr, 0, nullid, nullid)
1203 node0 = f.add(b'0', None, tr, 0, nullid, nullid)
1205 node1 = f.add(b'1', None, tr, 1, node0, nullid)
1204 node1 = f.add(b'1', None, tr, 1, node0, nullid)
1206 f.add(b'2', None, tr, 2, node1, nullid)
1205 f.add(b'2', None, tr, 2, node1, nullid)
1207 f.add(b'3', None, tr, 3, node0, nullid)
1206 f.add(b'3', None, tr, 3, node0, nullid)
1208 f.add(b'4', None, tr, 4, node0, nullid)
1207 f.add(b'4', None, tr, 4, node0, nullid)
1209
1208
1210 for rev in range(5):
1209 for rev in range(5):
1211 self.assertEqual(f.getstrippoint(rev), (rev, set()))
1210 self.assertEqual(f.getstrippoint(rev), (rev, set()))
1212
1211
1213 def testgetstrippointearlierlinkrevs(self):
1212 def testgetstrippointearlierlinkrevs(self):
1214 f = self._makefilefn()
1213 f = self._makefilefn()
1215
1214
1216 with self._maketransactionfn() as tr:
1215 with self._maketransactionfn() as tr:
1217 node0 = f.add(b'0', None, tr, 0, nullid, nullid)
1216 node0 = f.add(b'0', None, tr, 0, nullid, nullid)
1218 f.add(b'1', None, tr, 10, node0, nullid)
1217 f.add(b'1', None, tr, 10, node0, nullid)
1219 f.add(b'2', None, tr, 5, node0, nullid)
1218 f.add(b'2', None, tr, 5, node0, nullid)
1220
1219
1221 self.assertEqual(f.getstrippoint(0), (0, set()))
1220 self.assertEqual(f.getstrippoint(0), (0, set()))
1222 self.assertEqual(f.getstrippoint(1), (1, set()))
1221 self.assertEqual(f.getstrippoint(1), (1, set()))
1223 self.assertEqual(f.getstrippoint(2), (1, set()))
1222 self.assertEqual(f.getstrippoint(2), (1, set()))
1224 self.assertEqual(f.getstrippoint(3), (1, set()))
1223 self.assertEqual(f.getstrippoint(3), (1, set()))
1225 self.assertEqual(f.getstrippoint(4), (1, set()))
1224 self.assertEqual(f.getstrippoint(4), (1, set()))
1226 self.assertEqual(f.getstrippoint(5), (1, set()))
1225 self.assertEqual(f.getstrippoint(5), (1, set()))
1227 self.assertEqual(f.getstrippoint(6), (1, {2}))
1226 self.assertEqual(f.getstrippoint(6), (1, {2}))
1228 self.assertEqual(f.getstrippoint(7), (1, {2}))
1227 self.assertEqual(f.getstrippoint(7), (1, {2}))
1229 self.assertEqual(f.getstrippoint(8), (1, {2}))
1228 self.assertEqual(f.getstrippoint(8), (1, {2}))
1230 self.assertEqual(f.getstrippoint(9), (1, {2}))
1229 self.assertEqual(f.getstrippoint(9), (1, {2}))
1231 self.assertEqual(f.getstrippoint(10), (1, {2}))
1230 self.assertEqual(f.getstrippoint(10), (1, {2}))
1232 self.assertEqual(f.getstrippoint(11), (3, set()))
1231 self.assertEqual(f.getstrippoint(11), (3, set()))
1233
1232
1234 def teststripempty(self):
1233 def teststripempty(self):
1235 f = self._makefilefn()
1234 f = self._makefilefn()
1236
1235
1237 with self._maketransactionfn() as tr:
1236 with self._maketransactionfn() as tr:
1238 f.strip(0, tr)
1237 f.strip(0, tr)
1239
1238
1240 self.assertEqual(len(f), 0)
1239 self.assertEqual(len(f), 0)
1241
1240
1242 def teststripall(self):
1241 def teststripall(self):
1243 f = self._makefilefn()
1242 f = self._makefilefn()
1244
1243
1245 with self._maketransactionfn() as tr:
1244 with self._maketransactionfn() as tr:
1246 p1 = nullid
1245 p1 = nullid
1247 for rev in range(10):
1246 for rev in range(10):
1248 p1 = f.add(b'%d' % rev, None, tr, rev, p1, nullid)
1247 p1 = f.add(b'%d' % rev, None, tr, rev, p1, nullid)
1249
1248
1250 self.assertEqual(len(f), 10)
1249 self.assertEqual(len(f), 10)
1251
1250
1252 with self._maketransactionfn() as tr:
1251 with self._maketransactionfn() as tr:
1253 f.strip(0, tr)
1252 f.strip(0, tr)
1254
1253
1255 self.assertEqual(len(f), 0)
1254 self.assertEqual(len(f), 0)
1256
1255
1257 def teststrippartial(self):
1256 def teststrippartial(self):
1258 f = self._makefilefn()
1257 f = self._makefilefn()
1259
1258
1260 with self._maketransactionfn() as tr:
1259 with self._maketransactionfn() as tr:
1261 f.add(b'0', None, tr, 0, nullid, nullid)
1260 f.add(b'0', None, tr, 0, nullid, nullid)
1262 node1 = f.add(b'1', None, tr, 5, nullid, nullid)
1261 node1 = f.add(b'1', None, tr, 5, nullid, nullid)
1263 node2 = f.add(b'2', None, tr, 10, nullid, nullid)
1262 node2 = f.add(b'2', None, tr, 10, nullid, nullid)
1264
1263
1265 self.assertEqual(len(f), 3)
1264 self.assertEqual(len(f), 3)
1266
1265
1267 with self._maketransactionfn() as tr:
1266 with self._maketransactionfn() as tr:
1268 f.strip(11, tr)
1267 f.strip(11, tr)
1269
1268
1270 self.assertEqual(len(f), 3)
1269 self.assertEqual(len(f), 3)
1271
1270
1272 with self._maketransactionfn() as tr:
1271 with self._maketransactionfn() as tr:
1273 f.strip(10, tr)
1272 f.strip(10, tr)
1274
1273
1275 self.assertEqual(len(f), 2)
1274 self.assertEqual(len(f), 2)
1276
1275
1277 with self.assertRaises(error.LookupError):
1276 with self.assertRaises(error.LookupError):
1278 f.rev(node2)
1277 f.rev(node2)
1279
1278
1280 with self._maketransactionfn() as tr:
1279 with self._maketransactionfn() as tr:
1281 f.strip(6, tr)
1280 f.strip(6, tr)
1282
1281
1283 self.assertEqual(len(f), 2)
1282 self.assertEqual(len(f), 2)
1284
1283
1285 with self._maketransactionfn() as tr:
1284 with self._maketransactionfn() as tr:
1286 f.strip(3, tr)
1285 f.strip(3, tr)
1287
1286
1288 self.assertEqual(len(f), 1)
1287 self.assertEqual(len(f), 1)
1289
1288
1290 with self.assertRaises(error.LookupError):
1289 with self.assertRaises(error.LookupError):
1291 f.rev(node1)
1290 f.rev(node1)
1292
1291
1293 def makeifileindextests(makefilefn, maketransactionfn, addrawrevisionfn):
1292 def makeifileindextests(makefilefn, maketransactionfn, addrawrevisionfn):
1294 """Create a unittest.TestCase class suitable for testing file storage.
1293 """Create a unittest.TestCase class suitable for testing file storage.
1295
1294
1296 ``makefilefn`` is a callable which receives the test case as an
1295 ``makefilefn`` is a callable which receives the test case as an
1297 argument and returns an object implementing the ``ifilestorage`` interface.
1296 argument and returns an object implementing the ``ifilestorage`` interface.
1298
1297
1299 ``maketransactionfn`` is a callable which receives the test case as an
1298 ``maketransactionfn`` is a callable which receives the test case as an
1300 argument and returns a transaction object.
1299 argument and returns a transaction object.
1301
1300
1302 ``addrawrevisionfn`` is a callable which receives arguments describing a
1301 ``addrawrevisionfn`` is a callable which receives arguments describing a
1303 low-level revision to add. This callable allows the insertion of
1302 low-level revision to add. This callable allows the insertion of
1304 potentially bad data into the store in order to facilitate testing.
1303 potentially bad data into the store in order to facilitate testing.
1305
1304
1306 Returns a type that is a ``unittest.TestCase`` that can be used for
1305 Returns a type that is a ``unittest.TestCase`` that can be used for
1307 testing the object implementing the file storage interface. Simply
1306 testing the object implementing the file storage interface. Simply
1308 assign the returned value to a module-level attribute and a test loader
1307 assign the returned value to a module-level attribute and a test loader
1309 should find and run it automatically.
1308 should find and run it automatically.
1310 """
1309 """
1311 d = {
1310 d = {
1312 r'_makefilefn': makefilefn,
1311 r'_makefilefn': makefilefn,
1313 r'_maketransactionfn': maketransactionfn,
1312 r'_maketransactionfn': maketransactionfn,
1314 r'_addrawrevisionfn': addrawrevisionfn,
1313 r'_addrawrevisionfn': addrawrevisionfn,
1315 }
1314 }
1316 return type(r'ifileindextests', (ifileindextests,), d)
1315 return type(r'ifileindextests', (ifileindextests,), d)
1317
1316
1318 def makeifiledatatests(makefilefn, maketransactionfn, addrawrevisionfn):
1317 def makeifiledatatests(makefilefn, maketransactionfn, addrawrevisionfn):
1319 d = {
1318 d = {
1320 r'_makefilefn': makefilefn,
1319 r'_makefilefn': makefilefn,
1321 r'_maketransactionfn': maketransactionfn,
1320 r'_maketransactionfn': maketransactionfn,
1322 r'_addrawrevisionfn': addrawrevisionfn,
1321 r'_addrawrevisionfn': addrawrevisionfn,
1323 }
1322 }
1324 return type(r'ifiledatatests', (ifiledatatests,), d)
1323 return type(r'ifiledatatests', (ifiledatatests,), d)
1325
1324
1326 def makeifilemutationtests(makefilefn, maketransactionfn, addrawrevisionfn):
1325 def makeifilemutationtests(makefilefn, maketransactionfn, addrawrevisionfn):
1327 d = {
1326 d = {
1328 r'_makefilefn': makefilefn,
1327 r'_makefilefn': makefilefn,
1329 r'_maketransactionfn': maketransactionfn,
1328 r'_maketransactionfn': maketransactionfn,
1330 r'_addrawrevisionfn': addrawrevisionfn,
1329 r'_addrawrevisionfn': addrawrevisionfn,
1331 }
1330 }
1332 return type(r'ifilemutationtests', (ifilemutationtests,), d)
1331 return type(r'ifilemutationtests', (ifilemutationtests,), d)
@@ -1,73 +1,74
1 # This test verifies the conformance of various classes to various
1 # This test verifies the conformance of various classes to various
2 # storage interfaces.
2 # storage interfaces.
3 from __future__ import absolute_import
3 from __future__ import absolute_import
4
4
5 import silenttestrunner
5 import silenttestrunner
6
6
7 from mercurial import (
7 from mercurial import (
8 error,
8 error,
9 filelog,
9 filelog,
10 revlog,
10 revlog,
11 transaction,
11 transaction,
12 ui as uimod,
12 ui as uimod,
13 vfs as vfsmod,
13 vfs as vfsmod,
14 )
14 )
15
15
16 from mercurial.testing import (
16 from mercurial.testing import (
17 storage as storagetesting,
17 storage as storagetesting,
18 )
18 )
19
19
20 STATE = {
20 STATE = {
21 'lastindex': 0,
21 'lastindex': 0,
22 'ui': uimod.ui(),
22 'ui': uimod.ui(),
23 'vfs': vfsmod.vfs(b'.', realpath=True),
23 'vfs': vfsmod.vfs(b'.', realpath=True),
24 }
24 }
25
25
26 def makefilefn(self):
26 def makefilefn(self):
27 """Factory for filelog instances."""
27 """Factory for filelog instances."""
28 fl = filelog.filelog(STATE['vfs'], b'filelog-%d' % STATE['lastindex'])
28 fl = filelog.filelog(STATE['vfs'], b'filelog-%d' % STATE['lastindex'])
29 STATE['lastindex'] += 1
29 STATE['lastindex'] += 1
30 return fl
30 return fl
31
31
32 def maketransaction(self):
32 def maketransaction(self):
33 vfsmap = {b'plain': STATE['vfs'], b'store': STATE['vfs']}
33 vfsmap = {b'plain': STATE['vfs'], b'store': STATE['vfs']}
34
34
35 return transaction.transaction(STATE['ui'].warn, STATE['vfs'], vfsmap,
35 return transaction.transaction(STATE['ui'].warn, STATE['vfs'], vfsmap,
36 b'journal', b'undo')
36 b'journal', b'undo')
37
37
38 def addrawrevision(self, fl, tr, node, p1, p2, linkrev, rawtext=None,
38 def addrawrevision(self, fl, tr, node, p1, p2, linkrev, rawtext=None,
39 delta=None, censored=False, ellipsis=False, extstored=False):
39 delta=None, censored=False, ellipsis=False, extstored=False):
40 flags = 0
40 flags = 0
41
41
42 if censored:
42 if censored:
43 flags |= revlog.REVIDX_ISCENSORED
43 flags |= revlog.REVIDX_ISCENSORED
44 if ellipsis:
44 if ellipsis:
45 flags |= revlog.REVIDX_ELLIPSIS
45 flags |= revlog.REVIDX_ELLIPSIS
46 if extstored:
46 if extstored:
47 flags |= revlog.REVIDX_EXTSTORED
47 flags |= revlog.REVIDX_EXTSTORED
48
48
49 if rawtext is not None:
49 if rawtext is not None:
50 fl._revlog.addrawrevision(rawtext, tr, linkrev, p1, p2, node, flags)
50 fl._revlog.addrawrevision(rawtext, tr, linkrev, p1, p2, node, flags)
51 elif delta is not None:
51 elif delta is not None:
52 raise error.Abort('support for storing raw deltas not yet supported')
52 fl._revlog.addrawrevision(rawtext, tr, linkrev, p1, p2, node, flags,
53 cachedelta=delta)
53 else:
54 else:
54 raise error.Abort('must supply rawtext or delta arguments')
55 raise error.Abort('must supply rawtext or delta arguments')
55
56
56 # We may insert bad data. Clear caches to prevent e.g. cache hits to
57 # We may insert bad data. Clear caches to prevent e.g. cache hits to
57 # bypass hash verification.
58 # bypass hash verification.
58 fl._revlog.clearcaches()
59 fl._revlog.clearcaches()
59
60
60 # Assigning module-level attributes that inherit from unittest.TestCase
61 # Assigning module-level attributes that inherit from unittest.TestCase
61 # is all that is needed to register tests.
62 # is all that is needed to register tests.
62 filelogindextests = storagetesting.makeifileindextests(makefilefn,
63 filelogindextests = storagetesting.makeifileindextests(makefilefn,
63 maketransaction,
64 maketransaction,
64 addrawrevision)
65 addrawrevision)
65 filelogdatatests = storagetesting.makeifiledatatests(makefilefn,
66 filelogdatatests = storagetesting.makeifiledatatests(makefilefn,
66 maketransaction,
67 maketransaction,
67 addrawrevision)
68 addrawrevision)
68 filelogmutationtests = storagetesting.makeifilemutationtests(makefilefn,
69 filelogmutationtests = storagetesting.makeifilemutationtests(makefilefn,
69 maketransaction,
70 maketransaction,
70 addrawrevision)
71 addrawrevision)
71
72
72 if __name__ == '__main__':
73 if __name__ == '__main__':
73 silenttestrunner.main(__name__)
74 silenttestrunner.main(__name__)
General Comments 0
You need to be logged in to leave comments. Login now