tests/test-racy-mutations.t
changeset 46607 e9901d01d135
child 47065 a12819559ccb
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/test-racy-mutations.t	Wed Feb 03 16:33:10 2021 -0800
@@ -0,0 +1,102 @@
+#testcases skip-detection fail-if-detected
+
+Test situations that "should" only be reproducible:
+- on networked filesystems, or
+- user using `hg debuglocks` to eliminate the lock file, or
+- something (that doesn't respect the lock file) writing to the .hg directory
+while we're running
+
+  $ hg init a
+  $ cd a
+
+  $ cat > "$TESTTMP/waitlock_editor.sh" <<EOF
+  >     [ -n "\${WAITLOCK_ANNOUNCE:-}" ] && touch "\${WAITLOCK_ANNOUNCE}"
+  >     f="\${WAITLOCK_FILE}"
+  >     start=\`date +%s\`
+  >     timeout=5
+  >     while [ \\( ! -f \$f \\) -a \\( ! -L \$f \\) ]; do
+  >         now=\`date +%s\`
+  >         if [ "\`expr \$now - \$start\`" -gt \$timeout ]; then
+  >             echo "timeout: \$f was not created in \$timeout seconds (it is now \$(date +%s))"
+  >             exit 1
+  >         fi
+  >         sleep 0.1
+  >     done
+  >     if [ \$# -gt 1 ]; then
+  >         cat "\$@"
+  >     fi
+  > EOF
+  $ chmod +x "$TESTTMP/waitlock_editor.sh"
+
+Things behave differently if we don't already have a 00changelog.i file when
+this all starts, so let's make one.
+
+  $ echo r0 > r0
+  $ hg commit -qAm 'r0'
+
+Start an hg commit that will take a while
+  $ EDITOR_STARTED="$(pwd)/.editor_started"
+  $ MISCHIEF_MANAGED="$(pwd)/.mischief_managed"
+  $ JOBS_FINISHED="$(pwd)/.jobs_finished"
+
+#if fail-if-detected
+  $ cat >> .hg/hgrc << EOF
+  > [debug]
+  > revlog.verifyposition.changelog = fail
+  > EOF
+#endif
+
+  $ echo foo > foo
+  $ (WAITLOCK_ANNOUNCE="${EDITOR_STARTED}" \
+  >      WAITLOCK_FILE="${MISCHIEF_MANAGED}" \
+  >           HGEDITOR="$TESTTMP/waitlock_editor.sh" \
+  >           hg commit -qAm 'r1 (foo)' --edit foo > .foo_commit_out 2>&1 ; touch "${JOBS_FINISHED}") &
+
+Wait for the "editor" to actually start
+  $ WAITLOCK_FILE="${EDITOR_STARTED}" "$TESTTMP/waitlock_editor.sh"
+
+Break the locks, and make another commit.
+  $ hg debuglocks -LW
+  $ echo bar > bar
+  $ hg commit -qAm 'r2 (bar)' bar
+  $ hg debugrevlogindex -c
+     rev linkrev nodeid       p1           p2
+       0       0 222799e2f90b 000000000000 000000000000
+       1       1 6f124f6007a0 222799e2f90b 000000000000
+
+Awaken the editor from that first commit
+  $ touch "${MISCHIEF_MANAGED}"
+And wait for it to finish
+  $ WAITLOCK_FILE="${JOBS_FINISHED}" "$TESTTMP/waitlock_editor.sh"
+
+#if skip-detection
+(Ensure there was no output)
+  $ cat .foo_commit_out
+And observe a corrupted repository -- rev 2's linkrev is 1, which should never
+happen for the changelog (the linkrev should always refer to itself).
+  $ hg debugrevlogindex -c
+     rev linkrev nodeid       p1           p2
+       0       0 222799e2f90b 000000000000 000000000000
+       1       1 6f124f6007a0 222799e2f90b 000000000000
+       2       1 ac80e6205bb2 222799e2f90b 000000000000
+#endif
+
+#if fail-if-detected
+  $ cat .foo_commit_out
+  transaction abort!
+  rollback completed
+  note: commit message saved in .hg/last-message.txt
+  note: use 'hg commit --logfile .hg/last-message.txt --edit' to reuse it
+  abort: 00changelog.i: file cursor at position 249, expected 121
+And no corruption in the changelog.
+  $ hg debugrevlogindex -c
+     rev linkrev nodeid       p1           p2
+       0       0 222799e2f90b 000000000000 000000000000
+       1       1 6f124f6007a0 222799e2f90b 000000000000
+And, because of transactions, there's none in the manifestlog either.
+  $ hg debugrevlogindex -m
+     rev linkrev nodeid       p1           p2
+       0       0 7b7020262a56 000000000000 000000000000
+       1       1 ad3fe36d86d9 7b7020262a56 000000000000
+#endif
+