##// END OF EJS Templates
tests: fix hooks in `test-transaction-rollback-on-revlog-split.t` for Windows...
Matt Harbison -
r52891:629ecced default
parent child Browse files
Show More
@@ -1,518 +1,518
1 1 Test correctness of revlog inline -> non-inline transition
2 2 ----------------------------------------------------------
3 3
4 4 We test various file length and naming pattern as this created issue in the
5 5 past.
6 6
7 7 Helper extension to intercept renames and kill process
8 8
9 9 $ cat > $TESTTMP/intercept_before_rename.py << EOF
10 10 > import os
11 11 > from mercurial import extensions, util
12 12 > from mercurial.testing import ps_util
13 13 >
14 14 > def extsetup(ui):
15 15 > def rename(orig, src, dest, *args, **kwargs):
16 16 > path = util.normpath(dest)
17 17 > if path.endswith(b'data/file.i'):
18 18 > ps_util.kill(os.getpid())
19 19 > return orig(src, dest, *args, **kwargs)
20 20 > extensions.wrapfunction(util, 'rename', rename)
21 21 > EOF
22 22
23 23 $ cat > $TESTTMP/intercept_after_rename.py << EOF
24 24 > import os
25 25 > from mercurial import extensions, util
26 26 > from mercurial.testing import ps_util
27 27 >
28 28 > def extsetup(ui):
29 29 > def close(orig, *args, **kwargs):
30 30 > path = util.normpath(args[0]._atomictempfile__name)
31 31 > r = orig(*args, **kwargs)
32 32 > if path.endswith(b'/.hg/store/data/file.i'):
33 33 > ps_util.kill(os.getpid())
34 34 > return r
35 35 > extensions.wrapfunction(util.atomictempfile, 'close', close)
36 36 > def extsetup(ui):
37 37 > def rename(orig, src, dest, *args, **kwargs):
38 38 > path = util.normpath(dest)
39 39 > r = orig(src, dest, *args, **kwargs)
40 40 > if path.endswith(b'data/file.i'):
41 41 > ps_util.kill(os.getpid())
42 42 > return r
43 43 > extensions.wrapfunction(util, 'rename', rename)
44 44 > EOF
45 45
46 46 $ cat > $TESTTMP/killme.py << EOF
47 47 > import os
48 48 > from mercurial.testing import ps_util
49 49 >
50 50 > def killme(ui, repo, hooktype, **kwargs):
51 51 > ps_util.kill(os.getpid())
52 52 > EOF
53 53
54 54 $ cat > $TESTTMP/reader_wait_split.py << EOF
55 55 > import os
56 56 > import signal
57 57 > from mercurial import extensions, revlog, testing
58 58 > def _wait_post_load(orig, self, *args, **kwargs):
59 59 > wait = b'data/file' in self.radix
60 60 > if wait:
61 > testing.wait_file(b"$TESTTMP/writer-revlog-split")
61 > testing.wait_file(b"$TESTTMP_FORWARD_SLASH/writer-revlog-split")
62 62 > r = orig(self, *args, **kwargs)
63 63 > if wait:
64 > testing.write_file(b"$TESTTMP/reader-index-read")
65 > testing.wait_file(b"$TESTTMP/writer-revlog-unsplit")
64 > testing.write_file(b"$TESTTMP_FORWARD_SLASH/reader-index-read")
65 > testing.wait_file(b"$TESTTMP_FORWARD_SLASH/writer-revlog-unsplit")
66 66 > return r
67 67 >
68 68 > def extsetup(ui):
69 69 > extensions.wrapfunction(revlog.revlog, '_loadindex', _wait_post_load)
70 70 > EOF
71 71
72 72 setup a repository for tests
73 73 ----------------------------
74 74
75 75 $ cat >> $HGRCPATH << EOF
76 76 > [format]
77 77 > revlog-compression=none
78 78 > EOF
79 79
80 80 $ hg init troffset-computation
81 81 $ cd troffset-computation
82 82 $ files="
83 83 > file
84 84 > Directory_With,Special%Char/Complex_File.babar
85 85 > foo/bar/babar_celeste/foo
86 86 > 1234567890/1234567890/1234567890/1234567890/1234567890/1234567890/1234567890/1234567890/1234567890/1234567890/f
87 87 > some_dir/sub_dir/foo_bar
88 88 > some_dir/sub_dir/foo_bar.i.s/tutu
89 89 > "
90 90 $ for f in $files; do
91 91 > mkdir -p `dirname $f`
92 92 > done
93 93 $ for f in $files; do
94 94 > printf '%20d' '1' > $f
95 95 > done
96 96 $ hg commit -Aqma
97 97 $ for f in $files; do
98 98 > printf '%1024d' '1' > $f
99 99 > done
100 100 $ hg commit -Aqmb
101 101 $ for f in $files; do
102 102 > printf '%20d' '1' > $f
103 103 > done
104 104 $ hg commit -Aqmc
105 105 $ for f in $files; do
106 106 > dd if=/dev/zero of=$f bs=1k count=128 > /dev/null 2>&1
107 107 > done
108 108 $ hg commit -AqmD --traceback
109 109 $ for f in $files; do
110 110 > dd if=/dev/zero of=$f bs=1k count=132 > /dev/null 2>&1
111 111 > done
112 112 $ hg commit -AqmD --traceback
113 113
114 114 Reference size:
115 115 $ f -s file
116 116 file: size=135168
117 117 $ f -s .hg/store/data*/file*
118 118 .hg/store/data/file.d: size=267307
119 119 .hg/store/data/file.i: size=320
120 120
121 121 $ cd ..
122 122
123 123 Test a succesful pull
124 124 =====================
125 125
126 126 Make sure everything goes though as expect if we don't do any crash
127 127
128 128 $ hg clone --quiet --rev 1 troffset-computation troffset-success
129 129 $ cd troffset-success
130 130
131 131 Reference size:
132 132 $ f -s file
133 133 file: size=1024
134 134 $ f -s .hg/store/data/file*
135 135 .hg/store/data/file.i: size=1174
136 136
137 137 $ hg pull ../troffset-computation
138 138 pulling from ../troffset-computation
139 139 searching for changes
140 140 adding changesets
141 141 adding manifests
142 142 adding file changes
143 143 added 3 changesets with 18 changes to 6 files
144 144 new changesets c99a94cae9b1:64874a3b0160
145 145 (run 'hg update' to get a working copy)
146 146
147 147
148 148 The inline revlog has been replaced
149 149
150 150 $ f -s .hg/store/data/file*
151 151 .hg/store/data/file.d: size=267307
152 152 .hg/store/data/file.i: size=320
153 153
154 154
155 155 $ hg verify -q
156 156 $ cd ..
157 157
158 158
159 159 Test a hard crash after the file was split but before the transaction was committed
160 160 ===================================================================================
161 161
162 162 Test offset computation to correctly factor in the index entries themselves.
163 163 Also test that the new data size has the correct size if the transaction is aborted
164 164 after the index has been replaced.
165 165
166 166 Test repo has commits a, b, c, D, where D is large (grows the revlog enough that it
167 167 transitions to non-inline storage). The clone initially has changes a, b
168 168 and will transition to non-inline storage when adding c, D.
169 169
170 170 If the transaction adding c, D is rolled back, then we don't undo the revlog split,
171 171 but truncate the index and the data to remove both c and D.
172 172
173 173
174 174 $ hg clone --quiet --rev 1 troffset-computation troffset-computation-copy
175 175 $ cd troffset-computation-copy
176 176
177 177 Reference size:
178 178 $ f -s file
179 179 file: size=1024
180 180 $ f -s .hg/store/data*/file*
181 181 .hg/store/data/file.i: size=1174
182 182
183 183 $ cat > .hg/hgrc <<EOF
184 184 > [hooks]
185 185 > pretxnchangegroup = python:$TESTTMP/killme.py:killme
186 186 > EOF
187 187 #if chg
188 188 $ hg pull ../troffset-computation
189 189 pulling from ../troffset-computation
190 190 [255]
191 191 #else
192 192 $ hg pull ../troffset-computation
193 193 pulling from ../troffset-computation
194 194 *Killed* (glob)
195 195 [137]
196 196 #endif
197 197
198 198
199 199 The inline revlog still exist, but a split version exist next to it
200 200
201 201 $ cat .hg/store/journal | tr '\0' ' ' | grep '\.s'
202 202 data/some_dir/sub_dir/foo_bar.i.s/tutu.i 1174
203 203 data/some_dir/sub_dir/foo_bar.i.s/tutu.d 0
204 204 $ f -s .hg/store/data*/file*
205 205 .hg/store/data-s/file.i: size=320
206 206 .hg/store/data/file.d: size=267307
207 207 .hg/store/data/file.i: size=132395
208 208 $ f -s .hg/store/data*/foo*/bar*/babar__celeste*/foo*
209 209 .hg/store/data-s/foo/bar/babar__celeste/foo.i: size=320
210 210 .hg/store/data/foo/bar/babar__celeste/foo.d: size=267307
211 211 .hg/store/data/foo/bar/babar__celeste/foo.i: size=132395
212 212
213 213
214 214 The first file.i entry should match the "Reference size" above.
215 215 The first file.d entry is the temporary record during the split,
216 216
217 217 A "temporary file" entry exist for the split index.
218 218
219 219 $ cat .hg/store/journal | tr -s '\000' ' ' | grep data/file
220 220 data/file.i 1174
221 221 data/file.d 0
222 222 $ cat .hg/store/journal.backupfiles | tr -s '\000' ' ' | tr -s '\00' ' '| grep 'data.*/file'
223 223 data/file.i data/journal.backup.file.i.bck 0
224 224 data-s/file.i 0
225 225
226 226 recover is rolling the split back, the fncache is still valid
227 227
228 228 $ hg recover
229 229 rolling back interrupted transaction
230 230 (verify step skipped, run `hg verify` to check your repository content)
231 231 $ f -s .hg/store/data*/file*
232 232 .hg/store/data/file.i: size=1174
233 233 $ hg tip
234 234 changeset: 1:64b04c8dc267
235 235 tag: tip
236 236 user: test
237 237 date: Thu Jan 01 00:00:00 1970 +0000
238 238 summary: b
239 239
240 240 $ hg verify -q
241 241 $ hg debugrebuildfncache --only-data
242 242 fncache already up to date
243 243 $ hg verify -q
244 244 $ cd ..
245 245
246 246 Test a hard crash right before the index is move into place
247 247 ===========================================================
248 248
249 249 Now retry the procedure but intercept the rename of the index and check that
250 250 the journal does not contain the new index size. This demonstrates the edge case
251 251 where the data file is left as garbage.
252 252
253 253 $ hg clone --quiet --rev 1 troffset-computation troffset-computation-copy2
254 254 $ cd troffset-computation-copy2
255 255
256 256 Reference size:
257 257 $ f -s file
258 258 file: size=1024
259 259 $ f -s .hg/store/data*/file*
260 260 .hg/store/data/file.i: size=1174
261 261
262 262 $ cat > .hg/hgrc <<EOF
263 263 > [extensions]
264 264 > intercept_rename = $TESTTMP/intercept_before_rename.py
265 265 > EOF
266 266 #if chg
267 267 $ hg pull ../troffset-computation
268 268 pulling from ../troffset-computation
269 269 searching for changes
270 270 adding changesets
271 271 adding manifests
272 272 adding file changes
273 273 [255]
274 274 #else
275 275 $ hg pull ../troffset-computation
276 276 pulling from ../troffset-computation
277 277 searching for changes
278 278 adding changesets
279 279 adding manifests
280 280 adding file changes
281 281 *Killed* (glob)
282 282 [137]
283 283 #endif
284 284
285 285 The inline revlog still exist, but a split version exist next to it
286 286
287 287 $ f -s .hg/store/data*/file*
288 288 .hg/store/data-s/file.i: size=320
289 289 .hg/store/data/file.d: size=267307
290 290 .hg/store/data/file.i: size=132395
291 291
292 292 $ cat .hg/store/journal | tr -s '\000' ' ' | grep 'data.*/file'
293 293 data/file.i 1174
294 294 data/file.d 0
295 295
296 296 recover is rolling the split back, the fncache is still valid
297 297
298 298 $ hg recover
299 299 rolling back interrupted transaction
300 300 (verify step skipped, run `hg verify` to check your repository content)
301 301 $ f -s .hg/store/data*/file*
302 302 .hg/store/data/file.i: size=1174
303 303 $ hg tip
304 304 changeset: 1:64b04c8dc267
305 305 tag: tip
306 306 user: test
307 307 date: Thu Jan 01 00:00:00 1970 +0000
308 308 summary: b
309 309
310 310 $ hg verify -q
311 311 $ cd ..
312 312
313 313 Test a hard crash right after the index is move into place
314 314 ===========================================================
315 315
316 316 Now retry the procedure but intercept the rename of the index.
317 317
318 318 $ hg clone --quiet --rev 1 troffset-computation troffset-computation-crash-after-rename
319 319 $ cd troffset-computation-crash-after-rename
320 320
321 321 Reference size:
322 322 $ f -s file
323 323 file: size=1024
324 324 $ f -s .hg/store/data*/file*
325 325 .hg/store/data/file.i: size=1174
326 326
327 327 $ cat > .hg/hgrc <<EOF
328 328 > [extensions]
329 329 > intercept_rename = $TESTTMP/intercept_after_rename.py
330 330 > EOF
331 331 #if chg
332 332 $ hg pull ../troffset-computation
333 333 pulling from ../troffset-computation
334 334 searching for changes
335 335 adding changesets
336 336 adding manifests
337 337 adding file changes
338 338 [255]
339 339 #else
340 340 $ hg pull ../troffset-computation
341 341 pulling from ../troffset-computation
342 342 searching for changes
343 343 adding changesets
344 344 adding manifests
345 345 adding file changes
346 346 *Killed* (glob)
347 347 [137]
348 348 #endif
349 349
350 350 The inline revlog was over written on disk
351 351
352 352 $ f -s .hg/store/data*/file*
353 353 .hg/store/data/file.d: size=267307
354 354 .hg/store/data/file.i: size=320
355 355
356 356 $ cat .hg/store/journal | tr -s '\000' ' ' | grep 'data.*/file'
357 357 data/file.i 1174
358 358 data/file.d 0
359 359
360 360 recover is rolling the split back, the fncache is still valid
361 361
362 362 $ hg recover
363 363 rolling back interrupted transaction
364 364 (verify step skipped, run `hg verify` to check your repository content)
365 365 $ f -s .hg/store/data*/file*
366 366 .hg/store/data/file.i: size=1174
367 367 $ hg tip
368 368 changeset: 1:64b04c8dc267
369 369 tag: tip
370 370 user: test
371 371 date: Thu Jan 01 00:00:00 1970 +0000
372 372 summary: b
373 373
374 374 $ hg verify -q
375 375 $ cd ..
376 376
377 377 Have the transaction rollback itself without any hard crash
378 378 ===========================================================
379 379
380 380
381 381 Repeat the original test but let hg rollback the transaction.
382 382
383 383 $ hg clone --quiet --rev 1 troffset-computation troffset-computation-copy-rb
384 384 $ cd troffset-computation-copy-rb
385 385 $ cat > .hg/hgrc <<EOF
386 386 > [hooks]
387 387 > pretxnchangegroup = false
388 388 > EOF
389 389 $ hg pull ../troffset-computation
390 390 pulling from ../troffset-computation
391 391 searching for changes
392 392 adding changesets
393 393 adding manifests
394 394 adding file changes
395 395 transaction abort!
396 396 rollback completed
397 397 abort: pretxnchangegroup hook exited with status 1
398 398 [40]
399 399
400 400 The split was rollback
401 401
402 402 $ f -s .hg/store/data*/file*
403 403 .hg/store/data/file.i: size=1174
404 404
405 405 $ hg tip
406 406 changeset: 1:64b04c8dc267
407 407 tag: tip
408 408 user: test
409 409 date: Thu Jan 01 00:00:00 1970 +0000
410 410 summary: b
411 411
412 412 $ hg verify -q
413 413
414 414 $ cat > .hg/hgrc <<EOF
415 415 > [hooks]
416 416 > EOF
417 417 $ hg pull ../troffset-computation
418 418 pulling from ../troffset-computation
419 419 searching for changes
420 420 adding changesets
421 421 adding manifests
422 422 adding file changes
423 423 added 3 changesets with 18 changes to 6 files
424 424 new changesets c99a94cae9b1:64874a3b0160
425 425 (run 'hg update' to get a working copy)
426 426
427 427 $ f -s .hg/store/data*/file*
428 428 .hg/store/data/file.d: size=267307
429 429 .hg/store/data/file.i: size=320
430 430 $ hg verify -q
431 431
432 432 $ cd ..
433 433
434 434 Read race
435 435 =========
436 436
437 437 We check that a client that started reading a revlog (its index) after the
438 438 split and end reading (the data) after the rollback should be fine
439 439
440 440 $ hg clone --quiet --rev 1 troffset-computation troffset-computation-race
441 441 $ cd troffset-computation-race
442 442 $ cat > .hg/hgrc <<EOF
443 443 > [hooks]
444 > pretxnchangegroup=$RUNTESTDIR/testlib/wait-on-file 5 $TESTTMP/reader-index-read $TESTTMP/writer-revlog-split
444 > pretxnchangegroup=sh "$RUNTESTDIR/testlib/wait-on-file" 5 $TESTTMP/reader-index-read $TESTTMP/writer-revlog-split
445 445 > pretxnclose = false
446 446 > EOF
447 447
448 448 start a reader
449 449
450 450 $ hg cat --rev 0 file \
451 451 > --config "extensions.wait_read=$TESTTMP/reader_wait_split.py" \
452 452 > 2> $TESTTMP/reader.stderr \
453 453 > > $TESTTMP/reader.stdout &
454 454
455 455 Do a failed pull in //
456 456
457 457 $ hg pull ../troffset-computation
458 458 pulling from ../troffset-computation
459 459 searching for changes
460 460 adding changesets
461 461 adding manifests
462 462 adding file changes
463 463 transaction abort!
464 464 rollback completed
465 465 abort: pretxnclose hook exited with status 1
466 466 [40]
467 467 $ touch $TESTTMP/writer-revlog-unsplit
468 468 $ wait
469 469
470 470 The reader should be fine
471 471 $ cat $TESTTMP/reader.stderr
472 472 $ cat $TESTTMP/reader.stdout
473 473 1 (no-eol)
474 474
475 475 $ hg verify -q
476 476
477 477 $ cd ..
478 478
479 479 pending hooks
480 480 =============
481 481
482 482 We checks that hooks properly see the inside of the transaction, while other process don't.
483 483
484 484 $ hg clone --quiet --rev 1 troffset-computation troffset-computation-hooks
485 485 $ cd troffset-computation-hooks
486 486 $ cat > .hg/hgrc <<EOF
487 487 > [hooks]
488 > pretxnclose.01-echo = hg cat -r 'max(all())' file | f --size
489 > pretxnclose.02-echo = $RUNTESTDIR/testlib/wait-on-file 5 $TESTTMP/hook-done $TESTTMP/hook-tr-ready
488 > pretxnclose.01-echo = hg cat -r "max(all())" file | "$PYTHON" "$RUNTESTDIR/f" --size
489 > pretxnclose.02-echo = sh "$RUNTESTDIR/testlib/wait-on-file" 5 $TESTTMP/hook-done $TESTTMP/hook-tr-ready
490 490 > pretxnclose.03-abort = false
491 491 > EOF
492 492
493 493 $ (
494 494 > $RUNTESTDIR/testlib/wait-on-file 5 $TESTTMP/hook-tr-ready;\
495 495 > hg cat -r 'max(all())' file | f --size;\
496 496 > touch $TESTTMP/hook-done
497 497 > ) >stdout 2>stderr &
498 498
499 499 $ hg pull ../troffset-computation
500 500 pulling from ../troffset-computation
501 501 searching for changes
502 502 adding changesets
503 503 adding manifests
504 504 adding file changes
505 505 size=135168
506 506 transaction abort!
507 507 rollback completed
508 508 abort: pretxnclose.03-abort hook exited with status 1
509 509 [40]
510 510
511 511 $ cat stdout
512 512 size=1024
513 513 $ cat stderr
514 514
515 515 $ hg verify -q
516 516
517 517
518 518 $ cd ..
General Comments 0
You need to be logged in to leave comments. Login now