This should be useful for some shell invocation.
Details
Details
Diff Detail
Diff Detail
- Repository
 - rHG Mercurial
 - Lint
 Automatic diff as part of commit; lint not applicable. - Unit
 Automatic diff as part of commit; unit tests not applicable. 
This should be useful for some shell invocation.
| Automatic diff as part of commit; lint not applicable. | 
| Automatic diff as part of commit; unit tests not applicable. | 
| Path | Packages | |||
|---|---|---|---|---|
| M | tests/run-tests.py (6 lines) | |||
| M | tests/test-racy-mutations.t (16 lines) | 
| def defineport(i): | def defineport(i): | ||||
| offset = '' if i == 0 else '%s' % i | offset = '' if i == 0 else '%s' % i | ||||
| env["HGPORT%s" % offset] = '%s' % (self._startport + i) | env["HGPORT%s" % offset] = '%s' % (self._startport + i) | ||||
| env = os.environ.copy() | env = os.environ.copy() | ||||
| env['PYTHONUSERBASE'] = sysconfig.get_config_var('userbase') or '' | env['PYTHONUSERBASE'] = sysconfig.get_config_var('userbase') or '' | ||||
| env['HGEMITWARNINGS'] = '1' | env['HGEMITWARNINGS'] = '1' | ||||
| env['TESTTMP'] = _bytes2sys(self._testtmp) | env['TESTTMP'] = _bytes2sys(self._testtmp) | ||||
| # the FORWARD_SLASH version is useful when running `sh` on non unix | |||||
| # system (e.g. Windows) | |||||
| env['TESTTMP_FORWARD_SLASH'] = env['TESTTMP'].replace(os.sep, '/') | |||||
| uid_file = os.path.join(_bytes2sys(self._testtmp), 'UID') | uid_file = os.path.join(_bytes2sys(self._testtmp), 'UID') | ||||
| env['HGTEST_UUIDFILE'] = uid_file | env['HGTEST_UUIDFILE'] = uid_file | ||||
| env['TESTNAME'] = self.name | env['TESTNAME'] = self.name | ||||
| env['HOME'] = _bytes2sys(self._testtmp) | env['HOME'] = _bytes2sys(self._testtmp) | ||||
| if WINDOWS: | if WINDOWS: | ||||
| env['REALUSERPROFILE'] = env['USERPROFILE'] | env['REALUSERPROFILE'] = env['USERPROFILE'] | ||||
| # py3.8+ ignores HOME: https://bugs.python.org/issue36264 | # py3.8+ ignores HOME: https://bugs.python.org/issue36264 | ||||
| env['USERPROFILE'] = env['HOME'] | env['USERPROFILE'] = env['HOME'] | ||||
| def _run(self, testdescs): | def _run(self, testdescs): | ||||
| testdir = getcwdb() | testdir = getcwdb() | ||||
| # assume all tests in same folder for now | # assume all tests in same folder for now | ||||
| if testdescs: | if testdescs: | ||||
| pathname = os.path.dirname(testdescs[0]['path']) | pathname = os.path.dirname(testdescs[0]['path']) | ||||
| if pathname: | if pathname: | ||||
| testdir = os.path.join(testdir, pathname) | testdir = os.path.join(testdir, pathname) | ||||
| self._testdir = osenvironb[b'TESTDIR'] = testdir | self._testdir = osenvironb[b'TESTDIR'] = testdir | ||||
| osenvironb[b'TESTDIR_FORWARD_SLASH'] = osenvironb[b'TESTDIR'].replace(os.sep.encode('ascii'), b'/') | |||||
| if self.options.outputdir: | if self.options.outputdir: | ||||
| self._outputdir = canonpath(_sys2bytes(self.options.outputdir)) | self._outputdir = canonpath(_sys2bytes(self.options.outputdir)) | ||||
| else: | else: | ||||
| self._outputdir = getcwdb() | self._outputdir = getcwdb() | ||||
| if testdescs and pathname: | if testdescs and pathname: | ||||
| self._outputdir = os.path.join(self._outputdir, pathname) | self._outputdir = os.path.join(self._outputdir, pathname) | ||||
| previoustimes = {} | previoustimes = {} | ||||
| if self.options.order_by_runtime: | if self.options.order_by_runtime: | ||||
| osenvironb.pop(b'PYOXIDIZED_INSTALLED_AS_HG', None) | osenvironb.pop(b'PYOXIDIZED_INSTALLED_AS_HG', None) | ||||
| osenvironb[b"BINDIR"] = self._bindir | osenvironb[b"BINDIR"] = self._bindir | ||||
| osenvironb[b"PYTHON"] = PYTHON | osenvironb[b"PYTHON"] = PYTHON | ||||
| fileb = _sys2bytes(__file__) | fileb = _sys2bytes(__file__) | ||||
| runtestdir = os.path.abspath(os.path.dirname(fileb)) | runtestdir = os.path.abspath(os.path.dirname(fileb)) | ||||
| osenvironb[b'RUNTESTDIR'] = runtestdir | osenvironb[b'RUNTESTDIR'] = runtestdir | ||||
| osenvironb[b'RUNTESTDIR_FORWARD_SLASH'] = osenvironb[b'RUNTESTDIR'].replace(os.sep.encode('ascii'), b'/') | |||||
| if PYTHON3: | if PYTHON3: | ||||
| sepb = _sys2bytes(os.pathsep) | sepb = _sys2bytes(os.pathsep) | ||||
| else: | else: | ||||
| sepb = os.pathsep | sepb = os.pathsep | ||||
| path = [self._bindir, runtestdir] + osenvironb[b"PATH"].split(sepb) | path = [self._bindir, runtestdir] + osenvironb[b"PATH"].split(sepb) | ||||
| if os.path.islink(__file__): | if os.path.islink(__file__): | ||||
| # test helper will likely be at the end of the symlink | # test helper will likely be at the end of the symlink | ||||
| realfile = os.path.realpath(fileb) | realfile = os.path.realpath(fileb) | ||||
| #testcases skip-detection fail-if-detected | #testcases skip-detection fail-if-detected | ||||
| Test situations that "should" only be reproducible: | Test situations that "should" only be reproducible: | ||||
| - on networked filesystems, or | - on networked filesystems, or | ||||
| - user using `hg debuglocks` to eliminate the lock file, or | - user using `hg debuglocks` to eliminate the lock file, or | ||||
| - something (that doesn't respect the lock file) writing to the .hg directory | - something (that doesn't respect the lock file) writing to the .hg directory | ||||
| while we're running | while we're running | ||||
| $ hg init a | $ hg init a | ||||
| $ cd a | $ cd a | ||||
| $ cat > "$TESTTMP/waitlock_editor.sh" <<EOF | $ cat > "$TESTTMP_FORWARD_SLASH/waitlock_editor.sh" <<EOF | ||||
| > [ -n "\${WAITLOCK_ANNOUNCE:-}" ] && touch "\${WAITLOCK_ANNOUNCE}" | > [ -n "\${WAITLOCK_ANNOUNCE:-}" ] && touch "\${WAITLOCK_ANNOUNCE}" | ||||
| > f="\${WAITLOCK_FILE}" | > f="\${WAITLOCK_FILE}" | ||||
| > start=\`date +%s\` | > start=\`date +%s\` | ||||
| > timeout=5 | > timeout=5 | ||||
| > $RUNTESTDIR/testlib/wait-on-file "\$timeout" "\$f" | > "$RUNTESTDIR_FORWARD_SLASH/testlib/wait-on-file" "\$timeout" "\$f" | ||||
| > if [ \$# -gt 1 ]; then | > if [ \$# -gt 1 ]; then | ||||
| > cat "\$@" | > cat "\$@" | ||||
| > fi | > fi | ||||
| > EOF | > EOF | ||||
| Things behave differently if we don't already have a 00changelog.i file when | Things behave differently if we don't already have a 00changelog.i file when | ||||
| this all starts, so let's make one. | this all starts, so let's make one. | ||||
| $ echo r0 > r0 | $ echo r0 > r0 | ||||
| $ hg commit -qAm 'r0' | $ hg commit -qAm 'r0' | ||||
| Start an hg commit that will take a while | Start an hg commit that will take a while | ||||
| $ EDITOR_STARTED="$(pwd)/.editor_started" | $ EDITOR_STARTED="$TESTTMP_FORWARD_SLASH/a/.editor_started" | ||||
| $ MISCHIEF_MANAGED="$(pwd)/.mischief_managed" | $ MISCHIEF_MANAGED="$TESTTMP_FORWARD_SLASH/a/.mischief_managed" | ||||
| $ JOBS_FINISHED="$(pwd)/.jobs_finished" | $ JOBS_FINISHED="$TESTTMP_FORWARD_SLASH/a/.jobs_finished" | ||||
| #if fail-if-detected | #if fail-if-detected | ||||
| $ cat >> .hg/hgrc << EOF | $ cat >> .hg/hgrc << EOF | ||||
| > [debug] | > [debug] | ||||
| > revlog.verifyposition.changelog = fail | > revlog.verifyposition.changelog = fail | ||||
| > EOF | > EOF | ||||
| #endif | #endif | ||||
| $ cat >> .hg/hgrc << EOF | $ cat >> .hg/hgrc << EOF | ||||
| > [ui] | > [ui] | ||||
| > editor=sh $TESTTMP/waitlock_editor.sh | > editor=sh $TESTTMP_FORWARD_SLASH/waitlock_editor.sh | ||||
| > EOF | > EOF | ||||
| $ echo foo > foo | $ echo foo > foo | ||||
| $ (unset HGEDITOR; | $ (unset HGEDITOR; | ||||
| > WAITLOCK_ANNOUNCE="${EDITOR_STARTED}" \ | > WAITLOCK_ANNOUNCE="${EDITOR_STARTED}" \ | ||||
| > WAITLOCK_FILE="${MISCHIEF_MANAGED}" \ | > WAITLOCK_FILE="${MISCHIEF_MANAGED}" \ | ||||
| > hg commit -qAm 'r1 (foo)' --edit foo > .foo_commit_out 2>&1 ; touch "${JOBS_FINISHED}") & | > hg commit -qAm 'r1 (foo)' --edit foo > .foo_commit_out 2>&1 ; touch "${JOBS_FINISHED}") & | ||||
| Wait for the "editor" to actually start | Wait for the "editor" to actually start | ||||
| $ sh "$RUNTESTDIR/testlib/wait-on-file" 5 "${EDITOR_STARTED}" | $ sh "$RUNTESTDIR_FORWARD_SLASH/testlib/wait-on-file" 5 "${EDITOR_STARTED}" | ||||
| $ cat >> .hg/hgrc << EOF | $ cat >> .hg/hgrc << EOF | ||||
| > [ui] | > [ui] | ||||
| > editor= | > editor= | ||||
| > EOF | > EOF | ||||
| Break the locks, and make another commit. | Break the locks, and make another commit. | ||||
| $ hg debuglocks -LW | $ hg debuglocks -LW | ||||
| $ echo bar > bar | $ echo bar > bar | ||||
| $ hg commit -qAm 'r2 (bar)' bar | $ hg commit -qAm 'r2 (bar)' bar | ||||
| $ hg debugrevlogindex -c | $ hg debugrevlogindex -c | ||||
| rev linkrev nodeid p1 p2 | rev linkrev nodeid p1 p2 | ||||
| 0 0 222799e2f90b 000000000000 000000000000 | 0 0 222799e2f90b 000000000000 000000000000 | ||||
| 1 1 6f124f6007a0 222799e2f90b 000000000000 | 1 1 6f124f6007a0 222799e2f90b 000000000000 | ||||
| Awaken the editor from that first commit | Awaken the editor from that first commit | ||||
| $ touch "${MISCHIEF_MANAGED}" | $ touch "${MISCHIEF_MANAGED}" | ||||
| And wait for it to finish | And wait for it to finish | ||||
| $ WAITLOCK_FILE="${JOBS_FINISHED}" sh "$TESTTMP/waitlock_editor.sh" | $ WAITLOCK_FILE="${JOBS_FINISHED}" sh "$TESTTMP_FORWARD_SLASH/waitlock_editor.sh" | ||||
| #if skip-detection | #if skip-detection | ||||
| (Ensure there was no output) | (Ensure there was no output) | ||||
| $ cat .foo_commit_out | $ cat .foo_commit_out | ||||
| And observe a corrupted repository -- rev 2's linkrev is 1, which should never | 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). | happen for the changelog (the linkrev should always refer to itself). | ||||
| $ hg debugrevlogindex -c | $ hg debugrevlogindex -c | ||||
| rev linkrev nodeid p1 p2 | rev linkrev nodeid p1 p2 | ||||