hgext: fix many tests, run-tests, writecg2 for hg3.3

Summary: Still need to fix pushrebase

Test Plan: ##run-tests.py##

Reviewers: sid0, daviser, davidsp, mitrandir, akushner, rmcelroy, pyd, mpm, durham

Reviewed By: durham

Differential Revision: https://phabricator.fb.com/D1813630

Signature: t1:1813630:1422573745:c5ea2a8acdfda0e555d1ae56a16f4fb5e5618174
This commit is contained in:
Eric Sumner 2015-01-29 15:06:06 -08:00
parent f4ead350b0
commit 34002e0224
9 changed files with 143 additions and 61 deletions

View File

@ -60,6 +60,14 @@ import Queue as queue
from xml.dom import minidom
import unittest
try:
import json
except ImportError:
try:
import simplejson as json
except ImportError:
json = None
processlock = threading.Lock()
# subprocess._cleanup can race with any Popen.wait or Popen.poll on py24
@ -99,8 +107,6 @@ IMPL_PATH = 'PYTHONPATH'
if 'java' in sys.platform:
IMPL_PATH = 'JYTHONPATH'
TESTDIR = HGTMP = INST = BINDIR = TMPBINDIR = PYTHONDIR = None
defaults = {
'jobs': ('HGTEST_JOBS', 1),
'timeout': ('HGTEST_TIMEOUT', 180),
@ -186,6 +192,8 @@ def getparser():
" (default: $%s or %d)" % defaults['timeout'])
parser.add_option("--time", action="store_true",
help="time how long each test takes")
parser.add_option("--json", action="store_true",
help="store test result data in 'report.json' file")
parser.add_option("--tmpdir", type="string",
help="run tests in the given temporary directory"
" (implies --keep-tmpdir)")
@ -290,6 +298,7 @@ def getdiff(expected, output, ref, err):
lines = []
for line in difflib.unified_diff(expected, output, ref, err):
if line.startswith('+++') or line.startswith('---'):
line = line.replace('\\', '/')
if line.endswith(' \n'):
line = line[:-2] + '\n'
lines.append(line)
@ -491,7 +500,7 @@ class Test(unittest.TestCase):
except self.failureException, e:
# This differs from unittest in that we don't capture
# the stack trace. This is for historical reasons and
# this decision could be revisted in the future,
# this decision could be revisited in the future,
# especially for PythonTest instances.
if result.addFailure(self, str(e)):
success = True
@ -618,6 +627,8 @@ class Test(unittest.TestCase):
(r':%s\b' % self._startport, ':$HGPORT'),
(r':%s\b' % (self._startport + 1), ':$HGPORT1'),
(r':%s\b' % (self._startport + 2), ':$HGPORT2'),
(r'(?m)^(saved backup bundle to .*\.hg)( \(glob\))?$',
r'\1 (glob)'),
]
if os.name == 'nt':
@ -640,7 +651,8 @@ class Test(unittest.TestCase):
env["HGPORT2"] = str(self._startport + 2)
env["HGRCPATH"] = os.path.join(self._threadtmp, '.hgrc')
env["DAEMON_PIDS"] = os.path.join(self._threadtmp, 'daemon.pids')
env["HGEDITOR"] = sys.executable + ' -c "import sys; sys.exit(0)"'
env["HGEDITOR"] = ('"' + sys.executable + '"'
+ ' -c "import sys; sys.exit(0)"')
env["HGMERGE"] = "internal:merge"
env["HGUSER"] = "test"
env["HGENCODING"] = "ascii"
@ -673,11 +685,16 @@ class Test(unittest.TestCase):
hgrc.write('slash = True\n')
hgrc.write('interactive = False\n')
hgrc.write('mergemarkers = detailed\n')
hgrc.write('promptecho = True\n')
hgrc.write('[defaults]\n')
hgrc.write('backout = -d "0 0"\n')
hgrc.write('commit = -d "0 0"\n')
hgrc.write('shelve = --date "0 0"\n')
hgrc.write('tag = -d "0 0"\n')
hgrc.write('[largefiles]\n')
hgrc.write('usercache = %s\n' %
(os.path.join(self._testtmp, '.cache/largefiles')))
for opt in self._extraconfigopts:
section, key = opt.split('.', 1)
assert '=' in key, ('extra config opt %s must '
@ -710,6 +727,15 @@ class PythonTest(Test):
return result
# This script may want to drop globs from lines matching these patterns on
# Windows, but check-code.py wants a glob on these lines unconditionally. Don't
# warn if that is the case for anything matching these lines.
checkcodeglobpats = [
re.compile(r'^pushing to \$TESTTMP/.*[^)]$'),
re.compile(r'^moving \S+/.*[^)]$'),
re.compile(r'^pulling from \$TESTTMP/.*[^)]$')
]
class TTest(Test):
"""A "t test" is a test backed by a .t file."""
@ -760,7 +786,7 @@ class TTest(Test):
tdir = self._testdir.replace('\\', '/')
proc = Popen4('%s -c "%s/hghave %s"' %
(self._shell, tdir, ' '.join(reqs)),
self._testtmp, 0)
self._testtmp, 0, self._getenv())
stdout, stderr = proc.communicate()
ret = proc.wait()
if wifexited(ret):
@ -966,6 +992,9 @@ class TTest(Test):
if el + '\n' == l:
if os.altsep:
# matching on "/" is not needed for this line
for pat in checkcodeglobpats:
if pat.match(el):
return True
return '-glob'
return True
i, n = 0, len(el)
@ -998,6 +1027,9 @@ class TTest(Test):
if el.endswith(" (re)\n"):
return TTest.rematch(el[:-6], l)
if el.endswith(" (glob)\n"):
# ignore '(glob)' added to l by 'replacements'
if l.endswith(" (glob)\n"):
l = l[:-8] + "\n"
return TTest.globmatch(el[:-8], l)
if os.altsep and l.replace('\\', '/') == el:
return '+glob'
@ -1179,6 +1211,11 @@ class TestResult(unittest._TextTestResult):
def addOutputMismatch(self, test, ret, got, expected):
"""Record a mismatch in test output for a particular test."""
if self.shouldStop:
# don't print, some other test case already failed and
# printed, we're just stale and probably failed due to our
# temp dir getting cleaned up.
return
accepted = False
failed = False
@ -1191,28 +1228,30 @@ class TestResult(unittest._TextTestResult):
os.system("%s %s %s" %
(self._options.view, test.refpath, test.errpath))
else:
failed, lines = getdiff(expected, got,
test.refpath, test.errpath)
if failed:
self.addFailure(test, 'diff generation failed')
servefail, lines = getdiff(expected, got,
test.refpath, test.errpath)
if servefail:
self.addFailure(
test,
'server failed to start (HGPORT=%s)' % test._startport)
else:
self.stream.write('\n')
for line in lines:
self.stream.write(line)
self.stream.flush()
# 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 not accepted and not failed:
self.faildata[test.name] = ''.join(lines)
# 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 not accepted and not failed:
self.faildata[test.name] = ''.join(lines)
iolock.release()
return accepted
@ -1246,7 +1285,7 @@ class TestResult(unittest._TextTestResult):
iolock.release()
class TestSuite(unittest.TestSuite):
"""Custom unitest TestSuite that knows how to execute Mercurial tests."""
"""Custom unittest TestSuite that knows how to execute Mercurial tests."""
def __init__(self, testdir, jobs=1, whitelist=None, blacklist=None,
retest=False, keywords=None, loop=False,
@ -1419,6 +1458,43 @@ class TextTestRunner(unittest.TextTestRunner):
finally:
xuf.close()
if self._runner.options.json:
if json is None:
raise ImportError("json module not installed")
jsonpath = os.path.join(self._runner._testdir, 'report.json')
fp = open(jsonpath, 'w')
try:
timesd = {}
for test, cuser, csys, real in result.times:
timesd[test] = (real, cuser, csys)
outcome = {}
for tc in result.successes:
testresult = {'result': 'success',
'time': ('%0.3f' % timesd[tc.name][0]),
'cuser': ('%0.3f' % timesd[tc.name][1]),
'csys': ('%0.3f' % timesd[tc.name][2])}
outcome[tc.name] = testresult
for tc, err in sorted(result.faildata.iteritems()):
testresult = {'result': 'failure',
'time': ('%0.3f' % timesd[tc][0]),
'cuser': ('%0.3f' % timesd[tc][1]),
'csys': ('%0.3f' % timesd[tc][2])}
outcome[tc] = testresult
for tc, reason in result.skipped:
testresult = {'result': 'skip',
'time': ('%0.3f' % timesd[tc.name][0]),
'cuser': ('%0.3f' % timesd[tc.name][1]),
'csys': ('%0.3f' % timesd[tc.name][2])}
outcome[tc.name] = testresult
jsonout = json.dumps(outcome, sort_keys=True, indent=4)
fp.writelines(("testreport =", jsonout))
finally:
fp.close()
self._runner._checkhglib('Tested')
self.stream.writeln('# Ran %d tests, %d skipped, %d warned, %d failed.'
@ -1568,7 +1644,8 @@ class TestRunner(object):
os.environ["BINDIR"] = self._bindir
os.environ["PYTHON"] = PYTHON
path = [self._bindir] + os.environ["PATH"].split(os.pathsep)
runtestdir = os.path.abspath(os.path.dirname(__file__))
path = [self._bindir, runtestdir] + os.environ["PATH"].split(os.pathsep)
if self._tmpbindir != self._bindir:
path = [self._tmpbindir] + path
os.environ["PATH"] = os.pathsep.join(path)
@ -1577,8 +1654,7 @@ class TestRunner(object):
# can run .../tests/run-tests.py test-foo where test-foo
# adds an extension to HGRC. Also include run-test.py directory to
# import modules like heredoctest.
pypath = [self._pythondir, self._testdir,
os.path.abspath(os.path.dirname(__file__))]
pypath = [self._pythondir, self._testdir, runtestdir]
# We have to augment PYTHONPATH, rather than simply replacing
# it, in case external libraries are only available via current
# PYTHONPATH. (In particular, the Subversion bindings on OS X
@ -1588,6 +1664,9 @@ class TestRunner(object):
pypath.append(oldpypath)
os.environ[IMPL_PATH] = os.pathsep.join(pypath)
if self.options.pure:
os.environ["HGTEST_RUN_TESTS_PURE"] = "--pure"
self._coveragefile = os.path.join(self._testdir, '.coverage')
vlog("# Using TESTDIR", self._testdir)
@ -1841,8 +1920,8 @@ class TestRunner(object):
the one we expect it to be. If not, print a warning to stderr."""
if ((self._bindir == self._pythondir) and
(self._bindir != self._tmpbindir)):
# The pythondir has been infered from --with-hg flag.
# We cannot expect anything sensible here
# The pythondir has been inferred from --with-hg flag.
# We cannot expect anything sensible here.
return
expecthg = os.path.join(self._pythondir, 'mercurial')
actualhg = self._gethgpath()

View File

@ -188,7 +188,7 @@ fold a commit to check if other non-pick actions are handled correctly
$ hg histedit --continue
0 files updated, 0 files merged, 0 files removed, 0 files unresolved
0 files updated, 0 files merged, 0 files removed, 0 files unresolved
saved backup bundle to $TESTTMP/r/.hg/strip-backup/8f09d743de05-backup.hg
saved backup bundle to $TESTTMP/r/.hg/strip-backup/8f09d743de05-69b44d25-backup.hg (glob)
$ hg log --graph --template '{node|short} {desc} {files}\n'
@ 3c9ba74168ea f f

View File

@ -70,7 +70,7 @@ stop & continue cannot preserve hashes without obsolence
$ hg histedit --continue
0 files updated, 0 files merged, 0 files removed, 0 files unresolved
0 files updated, 0 files merged, 0 files removed, 0 files unresolved
saved backup bundle to $TESTTMP/r/.hg/strip-backup/e860deea161a-backup.hg
saved backup bundle to $TESTTMP/r/.hg/strip-backup/e860deea161a-fa46228d-backup.hg (glob)
$ hg log --graph
@ changeset: 5:794fe033d0a0
@ -122,14 +122,14 @@ stop on a commit
$ echo added > added
$ hg add added
$ hg commit --amend
saved backup bundle to $TESTTMP/r/.hg/strip-backup/d28623a90f2b-amend-backup.hg
saved backup bundle to $TESTTMP/r/.hg/strip-backup/d28623a90f2b-2e0800c1-amend-backup.hg (glob)
$ hg log -v -r '.' --template '{files}\n'
added e
$ hg histedit --continue
0 files updated, 0 files merged, 0 files removed, 0 files unresolved
0 files updated, 0 files merged, 0 files removed, 0 files unresolved
saved backup bundle to $TESTTMP/r/.hg/strip-backup/04d2fab98077-backup.hg
saved backup bundle to $TESTTMP/r/.hg/strip-backup/04d2fab98077-3b7c8dde-backup.hg (glob)
$ hg log --graph --template '{node|short} {desc} {files}\n'
@ 099559071076 f f
@ -181,7 +181,7 @@ fold a commit to check if other non-pick actions are handled correctly
$ hg histedit --continue
0 files updated, 0 files merged, 0 files removed, 0 files unresolved
0 files updated, 0 files merged, 0 files removed, 0 files unresolved
saved backup bundle to $TESTTMP/r/.hg/strip-backup/177f92b77385-backup.hg
saved backup bundle to $TESTTMP/r/.hg/strip-backup/177f92b77385-7102b3c2-backup.hg (glob)
$ hg log --graph --template '{node|short} {desc} {files}\n'
@ 3c9ba74168ea f f

View File

@ -22,7 +22,7 @@ Soft reset should leave pending changes
o b292c1e3311f
$ hg reset .^
saved backup bundle to $TESTTMP/repo/.hg/strip-backup/66ee28d0328c-backup.hg
saved backup bundle to $TESTTMP/repo/.hg/strip-backup/66ee28d0328c-b6ee89e7-backup.hg (glob)
$ hg log -G -T '{node|short} {bookmarks}\n'
@ b292c1e3311f foo
@ -38,7 +38,7 @@ Clean reset should overwrite all changes
$ hg commit -qAm y
$ hg reset --clean .^
saved backup bundle to $TESTTMP/repo/.hg/strip-backup/66ee28d0328c-backup.hg
saved backup bundle to $TESTTMP/repo/.hg/strip-backup/66ee28d0328c-b6ee89e7-backup.hg (glob)
$ hg diff
Reset should recover from backup bundles (with correct phase)
@ -108,7 +108,7 @@ Reset without a bookmark
$ hg book -d foo
$ hg reset .^
reseting without an active bookmark
saved backup bundle to $TESTTMP/repo/.hg/strip-backup/66ee28d0328c-backup.hg
saved backup bundle to $TESTTMP/repo/.hg/strip-backup/66ee28d0328c-b6ee89e7-backup.hg (glob)
$ hg book foo
Verify file status after reset
@ -127,13 +127,13 @@ Verify file status after reset
$ hg rm toberemoved
$ hg commit -m 'to be reset'
$ hg reset .^
saved backup bundle to $TESTTMP/repo/.hg/strip-backup/d36bf00ac47e-backup.hg
saved backup bundle to $TESTTMP/repo/.hg/strip-backup/d36bf00ac47e-375e6009-backup.hg (glob)
$ hg status
M x
! toberemoved
? tobeadded
$ hg reset -C 66ee28d0328c
saved backup bundle to $TESTTMP/repo/.hg/strip-backup/34fb347b2aae-backup.hg
saved backup bundle to $TESTTMP/repo/.hg/strip-backup/34fb347b2aae-c2a02721-backup.hg (glob)
Reset + Evolve tests

View File

@ -58,7 +58,7 @@ Basic test
With commit info
$ echo "hello" >c2 && hg ci --amend
saved backup bundle to $TESTTMP/repo/.hg/strip-backup/db92053d5c83-amend-backup.hg
saved backup bundle to $TESTTMP/repo/.hg/strip-backup/db92053d5c83-f9f5e1aa-amend-backup.hg (glob)
$ hg smartlog -T compact --commit-info
@ 5[tip][feature2] 05d10250273e 1970-01-01 00:00 +0000 test
| d

View File

@ -166,7 +166,7 @@ Verify strip -k resets dirstate correctly
4 files changed, 4 insertions(+), 2 deletions(-)
$ hg strip -r . -k
saved backup bundle to $TESTTMP/myrepo/.hg/strip-backup/39278f7c08a9-backup.hg
saved backup bundle to $TESTTMP/myrepo/.hg/strip-backup/39278f7c08a9-ce59e002-backup.hg (glob)
$ hg status
M show
? show2
@ -176,4 +176,4 @@ Verify rebase succeeds if all changed files are in sparse checkout
$ hg commit -Aqm "add show2"
$ hg rebase -d 1 --config extensions.rebase=
rebasing 2:bdde55290160 "add show2" (tip)
saved backup bundle to $TESTTMP/myrepo/.hg/strip-backup/bdde55290160-backup.hg
saved backup bundle to $TESTTMP/myrepo/.hg/strip-backup/bdde55290160-216ed9c6-backup.hg (glob)

View File

@ -82,7 +82,7 @@ Empty rebase fails
[255]
$ hg rebase -d 2
rebasing 1:7b4cb4e1674c "b"
saved backup bundle to $TESTTMP/repo/.hg/strip-backup/7b4cb4e1674c-backup.hg
saved backup bundle to $TESTTMP/repo/.hg/strip-backup/7b4cb4e1674c-f22b5b1e-backup.hg (glob)
Rebase fast forwards bookmark

View File

@ -34,8 +34,8 @@ bundle by itself shouldn't be changegroup2
a strip bundle should be changegroup2
$ hg strip 1
0 files updated, 0 files merged, 2 files removed, 0 files unresolved
saved backup bundle to $TESTTMP/repo/.hg/strip-backup/0e067c57feba-backup.hg
$ head -c 6 .hg/strip-backup/0e067c57feba-backup.hg
saved backup bundle to $TESTTMP/repo/.hg/strip-backup/0e067c57feba-3c242e3d-backup.hg (glob)
$ head -c 6 .hg/strip-backup/0e067c57feba-3c242e3d-backup.hg
HG2CBZ (no-eol)
applying bundle1 should continue to work
@ -58,7 +58,7 @@ applying bundle1 should continue to work
... and via pull
$ hg strip 1
saved backup bundle to $TESTTMP/repo/.hg/strip-backup/0e067c57feba-backup.hg
saved backup bundle to $TESTTMP/repo/.hg/strip-backup/0e067c57feba-3c242e3d-backup.hg (glob)
$ hg pull ../bundle.bundle
pulling from ../bundle.bundle
searching for changes
@ -69,13 +69,13 @@ applying bundle1 should continue to work
(run 'hg update' to get a working copy)
$ hg strip 1
saved backup bundle to $TESTTMP/repo/.hg/strip-backup/0e067c57feba-backup.hg
$ head -c 6 .hg/strip-backup/0e067c57feba-backup.hg
saved backup bundle to $TESTTMP/repo/.hg/strip-backup/0e067c57feba-3c242e3d-backup.hg (glob)
$ head -c 6 .hg/strip-backup/0e067c57feba-3c242e3d-backup.hg
HG2CBZ (no-eol)
hg incoming on a changegroup2 should work
$ hg incoming .hg/strip-backup/0e067c57feba-backup.hg
comparing with .hg/strip-backup/0e067c57feba-backup.hg
$ hg incoming .hg/strip-backup/0e067c57feba-3c242e3d-backup.hg
comparing with .hg/strip-backup/0e067c57feba-3c242e3d-backup.hg
searching for changes
changeset: 1:0e067c57feba
user: test
@ -89,7 +89,7 @@ hg incoming on a changegroup2 should work
summary: c
applying a changegroup2 should work via unbundle
$ hg unbundle .hg/strip-backup/0e067c57feba-backup.hg
$ hg unbundle .hg/strip-backup/0e067c57feba-3c242e3d-backup.hg
adding changesets
adding manifests
adding file changes
@ -98,11 +98,11 @@ applying a changegroup2 should work via unbundle
... and via pull
$ hg strip 1
saved backup bundle to $TESTTMP/repo/.hg/strip-backup/0e067c57feba-backup.hg
$ head -c 6 .hg/strip-backup/0e067c57feba-backup.hg
saved backup bundle to $TESTTMP/repo/.hg/strip-backup/0e067c57feba-3c242e3d-backup.hg (glob)
$ head -c 6 .hg/strip-backup/0e067c57feba-3c242e3d-backup.hg
HG2CBZ (no-eol)
$ hg pull .hg/strip-backup/0e067c57feba-backup.hg
pulling from .hg/strip-backup/0e067c57feba-backup.hg
$ hg pull .hg/strip-backup/0e067c57feba-3c242e3d-backup.hg
pulling from .hg/strip-backup/0e067c57feba-3c242e3d-backup.hg
searching for changes
adding changesets
adding manifests
@ -114,6 +114,6 @@ amends should also be cg2
$ hg up 2
2 files updated, 0 files merged, 0 files removed, 0 files unresolved
$ touch d && hg add d && hg ci --amend -mcd
saved backup bundle to $TESTTMP/repo/.hg/strip-backup/991a3460af53-amend-backup.hg
$ head -c 6 .hg/strip-backup/991a3460af53-amend-backup.hg
saved backup bundle to $TESTTMP/repo/.hg/strip-backup/991a3460af53-046ba7e5-amend-backup.hg (glob)
$ head -c 6 .hg/strip-backup/991a3460af53-046ba7e5-amend-backup.hg
HG2CBZ (no-eol)

View File

@ -28,17 +28,17 @@ from mercurial.node import nullid
import os
import tempfile
def overridewritebundle(orig, cg, filename, bundletype, vfs=None):
def overridewritebundle(orig, ui, cg, filename, bundletype, vfs=None):
if (bundletype.startswith('HG10') and
isinstance(cg, changegroup.cg2unpacker)):
bundletype = 'HG2C' + bundletype[4:]
return orig(cg, filename, bundletype, vfs=vfs)
return orig(ui, cg, filename, bundletype, vfs=vfs)
def overridechangegroupsubset(orig, repo, roots, heads, source):
def overridechangegroupsubset(orig, repo, roots, heads, source, version = '01'):
# we only care about performance for strips, not about 'hg bundle' and
# similar
if source != 'strip':
return orig(repo, roots, heads, source)
return orig(repo, roots, heads, source, version=version)
# below is all copied from changegroup.py, except with cg1 changed to
# cg2
@ -55,7 +55,9 @@ def overridechangegroupsubset(orig, repo, roots, heads, source):
bundler = changegroup.packermap['02'][0](repo)
gengroup = changegroup.getsubsetraw(repo, outgoing, bundler, source,
fastpath=False)
return changegroup.cg2unpacker(util.chunkbuffer(gengroup), 'UN')
result = changegroup.cg2unpacker(util.chunkbuffer(gengroup), 'UN')
result.version = '01' # needed to pass writebundle checks
return result
def overridereadbundle(orig, ui, fh, fname, vfs=None):
# copied from exchange.py
@ -143,8 +145,9 @@ def extsetup(ui):
# add bundle types for changegroup2
bundletypes = changegroup.bundletypes
cg2types = {}
for bundletype, (header, compressor) in bundletypes.iteritems():
for bundletype, hc in bundletypes.iteritems():
if bundletype.startswith('HG10'):
header, compressor = hc
cg2type = 'HG2C' + bundletype[4:]
cg2header = 'HG2C' + header[4:]
cg2types[cg2type] = (cg2header, compressor)