[PATCH 1 of 3] run-tests: do not prompt changes (-i) if a race condition is detected
Jun Wu
quark at fb.com
Wed Jun 21 08:13:19 UTC 2017
# HG changeset patch
# User Jun Wu <quark at fb.com>
# Date 1498032320 25200
# Wed Jun 21 01:05:20 2017 -0700
# Node ID 59730060864e3220227133cb9cd036720a329935
# Parent 0ce2cbebd74964ffe61e79de8941461bccc9371b
# Available At https://bitbucket.org/quark-zju/hg-draft
# hg pull https://bitbucket.org/quark-zju/hg-draft -r 59730060864e
run-tests: do not prompt changes (-i) if a race condition is detected
The race condition is like:
1. run-tests.py reads test-a.t as reference output, content A
2. run-tests.py runs the test (which could be content B, another race
condition fixed by the next patch, but assume it's content A here)
3. something changes test-a.t to content C
4. run-tests.py compares test output (content D) with content A
5. with "-i", run-tests.py prompts diff(A, D), while the file has content
C instead of A at this time
This patch detects the above case and tell the user to rerun the test if
they want to apply test changes.
diff --git a/tests/run-tests.py b/tests/run-tests.py
--- a/tests/run-tests.py
+++ b/tests/run-tests.py
@@ -634,14 +634,17 @@ class Test(unittest.TestCase):
self._chgsockdir = None
+ self._refout = self.readrefout()
+
+ def readrefout(self):
+ """read reference output"""
# If we're not in --debug mode and reference output file exists,
# check test output against it.
- if debug:
- self._refout = None # to match "out is None"
+ if self._debug:
+ return None # to match "out is None"
elif os.path.exists(self.refpath):
- f = open(self.refpath, 'rb')
- self._refout = f.read().splitlines(True)
- f.close()
+ with open(self.refpath, 'rb') as f:
+ return f.read().splitlines(True)
else:
- self._refout = []
+ return []
# needed to get base class __repr__ running
@@ -1589,12 +1592,17 @@ class TestResult(unittest._TextTestResul
# handle interactive prompt without releasing iolock
if self._options.interactive:
- self.stream.write('Accept this change? [n] ')
- answer = sys.stdin.readline().strip()
- if answer.lower() in ('y', 'yes'):
- if test.name.endswith('.t'):
- rename(test.errpath, test.path)
- else:
- rename(test.errpath, '%s.out' % test.path)
- accepted = True
+ if test.readrefout() != expected:
+ self.stream.write(
+ 'Reference output has changed (run again to prompt '
+ 'changes)')
+ else:
+ self.stream.write('Accept this change? [n] ')
+ answer = sys.stdin.readline().strip()
+ if answer.lower() in ('y', 'yes'):
+ if test.name.endswith('.t'):
+ rename(test.errpath, test.path)
+ else:
+ rename(test.errpath, '%s.out' % test.path)
+ accepted = True
if not accepted:
self.faildata[test.name] = b''.join(lines)
diff --git a/tests/test-run-tests.t b/tests/test-run-tests.t
--- a/tests/test-run-tests.t
+++ b/tests/test-run-tests.t
@@ -642,4 +642,31 @@ Accept the fix
saved backup bundle to $TESTTMP/*.hg (glob)<
+Race condition - test file was modified when test is running
+
+ $ TESTRACEDIR=`pwd`
+ $ export TESTRACEDIR
+ $ cat > test-race.t <<EOF
+ > $ echo 1
+ > $ echo "# a new line" >> $TESTRACEDIR/test-race.t
+ > EOF
+
+ $ rt -i test-race.t
+
+ --- $TESTTMP/test-race.t
+ +++ $TESTTMP/test-race.t.err
+ @@ -1,2 +1,3 @@
+ $ echo 1
+ + 1
+ $ echo "# a new line" >> $TESTTMP/test-race.t
+ Reference output has changed (run again to prompt changes)
+ ERROR: test-race.t output changed
+ !
+ Failed test-race.t: output changed
+ # Ran 1 tests, 0 skipped, 1 failed.
+ python hash seed: * (glob)
+ [1]
+
+ $ rm test-race.t
+
(reinstall)
$ mv backup test-failure.t
More information about the Mercurial-devel
mailing list