revlog: add a new test file focussed on testing transactionally issue
What we test here is currently also covered by `test-hooks.t`. However having
our own test file allow for more focussed/deep testing and to cover more variant
when relevant. So we create a new test file.
Differential Revision: https://phab.mercurial-scm.org/D10626
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/test-transaction-safety.t Mon May 03 12:34:31 2021 +0200
@@ -0,0 +1,186 @@
+Test transaction safety
+=======================
+
+This test basic case to make sure external process do not see transaction
+content until it is committed.
+
+# TODO: also add an external reader accessing revlog files while they are written
+# (instead of during transaction finalisation)
+
+# TODO: also add stream clone and hardlink clone happening during these transaction.
+
+setup
+-----
+
+synchronisation+output script:
+
+ $ mkdir sync
+ $ mkdir output
+ $ mkdir script
+ $ HG_TEST_FILE_EXT_WAITING=$TESTTMP/sync/ext_waiting
+ $ export HG_TEST_FILE_EXT_WAITING
+ $ HG_TEST_FILE_EXT_UNLOCK=$TESTTMP/sync/ext_unlock
+ $ export HG_TEST_FILE_EXT_UNLOCK
+ $ HG_TEST_FILE_EXT_DONE=$TESTTMP/sync/ext_done
+ $ export HG_TEST_FILE_EXT_DONE
+ $ cat << EOF > script/external.sh
+ > #!/bin/sh
+ > $RUNTESTDIR/testlib/wait-on-file 5 $HG_TEST_FILE_EXT_UNLOCK $HG_TEST_FILE_EXT_WAITING
+ > hg log --rev 'tip' -T 'external: {rev} {desc}\n' > $TESTTMP/output/external.out
+ > touch $HG_TEST_FILE_EXT_DONE
+ > EOF
+ $ chmod +x script/external.sh
+ $ cat << EOF > script/internal.sh
+ > #!/bin/sh
+ > hg log --rev 'tip' -T 'internal: {rev} {desc}\n' > $TESTTMP/output/internal.out
+ > $RUNTESTDIR/testlib/wait-on-file 5 $HG_TEST_FILE_EXT_DONE $HG_TEST_FILE_EXT_UNLOCK
+ > EOF
+ $ chmod +x script/internal.sh
+
+
+Automated commands:
+
+ $ make_one_commit() {
+ > rm -f $TESTTMP/sync/*
+ > rm -f $TESTTMP/output/*
+ > hg log --rev 'tip' -T 'pre-commit: {rev} {desc}\n'
+ > echo x >> a
+ > $TESTTMP/script/external.sh & hg commit -m "$1"
+ > cat $TESTTMP/output/external.out
+ > cat $TESTTMP/output/internal.out
+ > hg log --rev 'tip' -T 'post-tr: {rev} {desc}\n'
+ > }
+
+
+ $ make_one_pull() {
+ > rm -f $TESTTMP/sync/*
+ > rm -f $TESTTMP/output/*
+ > hg log --rev 'tip' -T 'pre-commit: {rev} {desc}\n'
+ > echo x >> a
+ > $TESTTMP/script/external.sh & hg pull ../other-repo/ --rev "$1" --force --quiet
+ > cat $TESTTMP/output/external.out
+ > cat $TESTTMP/output/internal.out
+ > hg log --rev 'tip' -T 'post-tr: {rev} {desc}\n'
+ > }
+
+prepare a large source to which to pull from:
+
+The source is large to unsure we don't use inline more after the pull
+
+ $ hg init other-repo
+ $ hg -R other-repo debugbuilddag .+500
+
+
+prepare an empty repository where to make test:
+
+ $ hg init repo
+ $ cd repo
+ $ touch a
+ $ hg add a
+
+prepare a small extension to controll inline size
+
+ $ mkdir $TESTTMP/ext
+ $ cat << EOF > $TESTTMP/ext/small_inline.py
+ > from mercurial import revlog
+ > revlog._maxinline = 64 * 100
+ > EOF
+
+
+
+
+ $ cat << EOF >> $HGRCPATH
+ > [extensions]
+ > small_inline=$TESTTMP/ext/small_inline.py
+ > [hooks]
+ > pretxnclose = $TESTTMP/script/internal.sh
+ > EOF
+
+check this is true for the initial commit (inline → inline)
+-----------------------------------------------------------
+
+the repository should still be inline (for relevant format)
+
+ $ make_one_commit first
+ pre-commit: -1
+ external: -1
+ internal: 0 first
+ post-tr: 0 first
+ $ hg debugrevlog -c | grep inline
+ flags : inline
+
+check this is true for extra commit (inline → inline)
+-----------------------------------------------------
+
+the repository should still be inline (for relevant format)
+
+ $ hg debugrevlog -c | grep inline
+ flags : inline
+ $ make_one_commit second
+ pre-commit: 0 first
+ external: 0 first
+ internal: 1 second
+ post-tr: 1 second
+ $ hg debugrevlog -c | grep inline
+ flags : inline
+
+check this is true for a small pull (inline → inline)
+-----------------------------------------------------
+
+the repository should still be inline (for relevant format)
+
+ $ hg debugrevlog -c | grep inline
+ flags : inline
+ $ make_one_pull 3
+ pre-commit: 1 second
+ warning: repository is unrelated
+ external: 1 second
+ internal: 5 r3
+ post-tr: 5 r3
+ $ hg debugrevlog -c | grep inline
+ flags : inline
+
+Make a large pull (inline → no-inline)
+---------------------------------------
+
+the repository should no longer be inline (for relevant format)
+
+ $ hg debugrevlog -c | grep inline
+ flags : inline
+ $ make_one_pull 400
+ pre-commit: 5 r3
+ external: 5 r3
+ internal: 402 r400
+ post-tr: 402 r400
+ $ hg debugrevlog -c | grep inline
+ [1]
+
+check this is true for extra commit (no-inline → no-inline)
+-----------------------------------------------------------
+
+the repository should no longer be inline (for relevant format)
+ $ hg debugrevlog -c | grep inline
+ [1]
+ $ make_one_commit third
+ pre-commit: 402 r400
+ external: 402 r400
+ internal: 403 third
+ post-tr: 403 third
+ $ hg debugrevlog -c | grep inline
+ [1]
+
+
+Make a pull (not-inline → no-inline)
+-------------------------------------
+
+the repository should no longer be inline (for relevant format)
+
+ $ hg debugrevlog -c | grep inline
+ [1]
+ $ make_one_pull tip
+ pre-commit: 403 third
+ external: 403 third
+ internal: 503 r500
+ post-tr: 503 r500
+ $ hg debugrevlog -c | grep inline
+ [1]