Commit 5aebd8f0 authored by Yuya Nishihara's avatar Yuya Nishihara

merge default into stable (freeze for 5.5)

--HG--
branch : stable
Pipeline #8326 failed with stage
in 20 minutes and 9 seconds
......@@ -55,3 +55,4 @@ contrib/packaging/macos/toolchain/downloads
contrib/packaging/macos/toolchain/toolchain-qt4
contrib/packaging/macos/toolchain/toolchain-qt5
contrib/packaging/macos/releases
.pytest_cache
......@@ -32,8 +32,8 @@ local:
tests:
@[ -n "$(HGPATH)" ] || { echo "HGPATH not specified"; false; }
@[ -d "$(HGPATH)" ] || { echo "HGPATH not found: $(HGPATH)"; false; }
$(PYTHON) tests/run-tests.py -a '!extensions' --with-doctest
$(PYTHON) tests/run-tests.py -a extensions=largefiles
$(PYTHON) tests/run-tests.py -m 'not largefiles' --doctest-modules tests
$(PYTHON) tests/run-tests.py -m largefiles tests
$(PYTHON) tests/run-hgtests.py
.PHONY: pytype
......
......@@ -3,12 +3,12 @@ import sys
from nose.tools import *
from tortoisehg.util import colormap
def setup():
def setup_module():
global _origmaxint
_origmaxint = sys.maxsize
sys.maxsize = int((1 << 31) - 1)
def teardown():
def teardown_module():
sys.maxsize = _origmaxint
def fakectx(userhash, date, tz=0):
......
import functools
import os
from nose.tools import *
import pytest
from tortoisehg.hgqt import filedata, thgrepo
import helpers
def setup():
def setup_module():
global _tmpdir
_tmpdir = helpers.mktmpdir(__name__)
......@@ -40,30 +42,32 @@ def loaddata(reponame, rev, path, prev=None):
return fd
def check_error(fd, message):
@pytest.mark.parametrize('get_fd, message', [
(functools.partial(loaddata, 'status', rev, path + sfx), msg)
for rev, sfx in [(0, ''), (1, '.copied'), (2, '.renamed')]
for path, msg in [('binary', 'is binary'),
('text-over1kb', 'is larger than')]
])
def test_error_added(get_fd, message):
fd = get_fd()
assert message in fd.error, (message, fd.error)
# no data should be loaded
assert_false(fd.contents)
assert_false(fd.olddata)
assert_false(fd.diff)
def test_error_added():
for rev, sfx in [(0, ''), (1, '.copied'), (2, '.renamed')]:
for path, msg in [('binary', 'is binary'),
('text-over1kb', 'is larger than')]:
fd = loaddata('status', rev, path + sfx)
yield check_error, fd, msg
def check_flabel(fd, message):
assert message in fd.flabel, (message, fd.flabel)
def test_flabel_added():
for path in ['text', 'binary', 'text-over1kb']:
for rev, sfx, msg in [(0, '', 'added'),
(1, '.copied', 'copied from'),
(2, '.renamed', 'renamed from')]:
fd = loaddata('status', rev, path + sfx)
yield check_flabel, fd, msg
@pytest.mark.parametrize('get_fd, message', [
(functools.partial(loaddata, 'status', rev, path + sfx), msg)
for path in ['text', 'binary', 'text-over1kb']
for rev, sfx, msg in [(0, '', 'added'),
(1, '.copied', 'copied from'),
(2, '.renamed', 'renamed from')]
])
def test_flabel_added(get_fd, message):
check_flabel(get_fd(), message)
def test_flabel_far_rename():
fd = loaddata('status', 2, 'text.copied', 0)
......
......@@ -10,7 +10,7 @@ from tortoisehg.util import hglib
import helpers
def setup():
def setup_module():
global _tmpdir
_tmpdir = helpers.mktmpdir(__name__)
......
......@@ -8,7 +8,7 @@ from tortoisehg.util import hglib
import helpers
def setup():
def setup_module():
global _tmpdir
_tmpdir = helpers.mktmpdir(__name__)
......
......@@ -2,13 +2,14 @@
import os
from nose.tools import *
import pytest
from mercurial import hg
from tortoisehg.util import hglib
import helpers
def setup():
def setup_module():
global _tmpdir
_tmpdir = helpers.mktmpdir(__name__)
......@@ -44,15 +45,14 @@ def setup_repoid():
hg = helpers.HgClient(os.path.join(_tmpdir, 'repoid-rev0hidden'))
hg.debugobsolete(_repoidnodes[0])
def check_repoid(reponame, rootrev):
@pytest.mark.parametrize('reponame, rootrev', [
('empty', -1),
('repoid-trivial', 0),
('repoid-allhidden', -1),
('repoid-rev0hidden', 1)
])
def test_repoid(reponame, rootrev):
repo = openrepo(reponame)
nodehex = _repoidnodes[rootrev]
assert_equal(nodehex[:12], hglib.shortrepoid(repo))
assert_equal(nodehex.decode('hex'), hglib.repoidnode(repo))
def test_repoid():
for reponame, rev in [('empty', -1),
('repoid-trivial', 0),
('repoid-allhidden', -1),
('repoid-rev0hidden', 1)]:
yield check_repoid, reponame, rev
"""Test for compatibility with Mercurial API"""
import inspect
import pytest
from nose.tools import *
from tortoisehg.util import hglib, pipeui
def assert_same_argspec(f, g):
def test_same_argspec(f, g):
fa, ga = inspect.getargspec(f), inspect.getargspec(g)
assert_equals(fa, ga,
'%s != %s' % (inspect.formatargspec(*fa),
......@@ -13,13 +15,13 @@ def assert_same_argspec(f, g):
def overridden_methods(cls):
basemethods = inspect.getmembers(cls.__base__, inspect.ismethod)
return [(name, basemeth, getattr(cls, name))
return [(basemeth, getattr(cls, name))
for name, basemeth in basemethods
if basemeth.__func__ is not getattr(cls, name).__func__]
def test_pipeui():
def pytest_generate_tests(metafunc):
ui = hglib.loadui()
pipeui.uisetup(ui)
for name, basemeth, meth in overridden_methods(ui.__class__):
yield assert_same_argspec, basemeth, meth
if metafunc.function == test_same_argspec:
metafunc.parametrize('f, g', overridden_methods(ui.__class__))
"""Nose plugin to capture unhandled exception"""
import sys
from nose import plugins
class CaptureExcPlugin(plugins.Plugin):
"""Capture unhandled exception (probably raised inside event loop)"""
enabled = False
name = 'capture-exc'
def options(self, parser, env):
parser.add_option('--no-capture-exc', dest='capture_exc',
action='store_false', default=True,
help='Catch unhandled exception to report as error')
def configure(self, options, conf):
self.enabled = options.capture_exc
def prepareTestResult(self, result):
# dirty hack to access result.addError()
self._result = result
def startTest(self, test):
self._origexcepthook = sys.excepthook
sys.excepthook = self._excepthook
self._excepts = []
def stopTest(self, test):
sys.excepthook = self._origexcepthook
del self._origexcepthook
if self._excepts:
# BUG: because the corresponding addSuccess/Failure/Error for the
# given test is already called, this increases the test counts.
self._result.addError(test, self._excepts.pop(0))
def _excepthook(self, type, value, traceback):
self._excepts.append((type, value, traceback))
[pytest]
markers =
largefiles: enable largefiles extensions
"""Pytest plugin to capture unhandled exception"""
from __future__ import print_function
try:
from cStringIO import StringIO
except ImportError:
try:
from StringIO import StringIO
except ImportError:
from io import StringIO
import sys
import traceback
import pytest
class CaptureExcPlugin(object):
"""Capture unhandled exception (probably raised inside event loop)"""
def pytest_addoption(self, parser):
parser.addoption('--no-capture-exc', dest='capture_exc',
action='store_false', default=True,
help='Catch unhandled exception to report as error')
def pytest_configure(self, config):
options = config.known_args_namespace
self.enabled = options.capture_exc
@pytest.mark.hookwrapper
def pytest_runtest_call(self, item):
self._origexcepthook = sys.excepthook
sys.excepthook = self._excepthook
self._excepts = []
try:
yield
finally:
sys.excepthook = self._origexcepthook
del self._origexcepthook
if self._excepts:
out = StringIO()
print("%s uncaught exception(s):" % len(self._excepts), file=out)
for exc_info in self._excepts:
print(file=out)
traceback.print_exception(*exc_info, file=out)
del self._excepts[:]
pytest.fail(out.getvalue(), pytrace=False)
def _excepthook(self, type, value, traceback):
self._excepts.append((type, value, traceback))
"""Nose plugin to set up test environment"""
"""Pytest plugin to set up test environment"""
from __future__ import absolute_import
......@@ -7,27 +7,28 @@ import shutil
import sys
import tempfile
from nose import plugins
import pytest
# don't import mercurial or tortoisehg before setting up test environment
class HgEnvPlugin(plugins.Plugin):
class HgEnvPlugin(object):
"""Set up temporary environment"""
enabled = True
name = 'hgenv'
def options(self, parser, env):
parser.add_option('--keep-tmpdir', action='store_true', default=False,
help='Keep temporary directory after running tests')
parser.add_option('--tmpdir',
help=('Put temporary files in the given directory '
'(implies --keep-tmpdir)'))
def pytest_addoption(self, parser):
parser.addoption('--keep-tmpdir', action='store_true', default=False,
help='Keep temporary directory after running tests')
parser.addoption('--tmpdir',
help=('Put temporary files in the given directory '
'(implies --keep-tmpdir)'))
def configure(self, options, conf):
def pytest_configure(self, config):
options = config.known_args_namespace
self.keep_tmpdir = options.keep_tmpdir or bool(options.tmpdir)
self.tmpdir = options.tmpdir
def begin(self):
@pytest.hookimpl(tryfirst=True)
def pytest_collection(self):
if 'mercurial' in sys.modules:
raise Exception('loaded mercurial module before setting up '
'test environment')
......@@ -124,7 +125,7 @@ class HgEnvPlugin(plugins.Plugin):
QSettings.setPath(QSettings.IniFormat, QSettings.UserScope,
self.configdir)
def finalize(self, result):
def pytest_sessionfinish(self):
del self._qapp
if not self.keep_tmpdir:
......
......@@ -55,7 +55,7 @@ def waitForCmdStarted(session, timeout=5000):
loop.exec_()
class _CmdAgentTestBase(unittest.TestCase):
class _CmdAgentTestBase(object):
@classmethod
def setUpClass(cls):
tmpdir = helpers.mktmpdir(cls.__name__)
......@@ -247,11 +247,11 @@ class _CmdAgentTestBase(unittest.TestCase):
self.assertFalse(self.agent.isBusy())
class CmdAgentProcTest(_CmdAgentTestBase):
class CmdAgentProcTest(_CmdAgentTestBase, unittest.TestCase):
workername = 'proc'
class CmdAgentServerTest(_CmdAgentTestBase):
class CmdAgentServerTest(_CmdAgentTestBase, unittest.TestCase):
workername = 'server'
@classmethod
......
......@@ -11,6 +11,8 @@ from mercurial import (
from nose.plugins.skip import SkipTest
import pytest
from tortoisehg.hgqt.qtcore import (
QModelIndex,
Qt,
......@@ -27,7 +29,7 @@ from tortoisehg.hgqt.manifestmodel import ManifestModel
import helpers
def setup():
def setup_module():
# necessary for style().standardIcon()
if not isinstance(QApplication.instance(), QApplication):
raise SkipTest
......@@ -637,9 +639,8 @@ class ManifestModelReloadTest(unittest.TestCase):
self.assertEqual(['bar', 'foo'], alldata(m))
@pytest.mark.largefiles
class ManifestModelLargeFilesTest(unittest.TestCase):
extensions = ['largefiles']
@classmethod
def setUpClass(cls):
cls.hg = hg = helpers.HgClient(os.path.join(_tmpdir, cls.__name__))
......
......@@ -50,7 +50,7 @@ class RepoAgentAttributeTest(unittest.TestCase):
self.assertFalse(self.agent.hiddenRevsIncluded())
class _RepoAgentChangedSignalTestBase(unittest.TestCase):
class _RepoAgentChangedSignalTestBase(object):
@classmethod
def setUpClass(cls):
tmpdir = helpers.mktmpdir(cls.__name__)
......@@ -198,7 +198,7 @@ class _RepoAgentChangedSignalTestBase(unittest.TestCase):
self.wait_changed(thgrepo.LogChanged)
class RepoAgentChangedSignalWithMonitorTest(_RepoAgentChangedSignalTestBase):
class RepoAgentChangedSignalWithMonitorTest(_RepoAgentChangedSignalTestBase, unittest.TestCase):
monitorrepo = b'always'
def test_filesystem_watcher(self):
......@@ -225,5 +225,5 @@ class RepoAgentChangedSignalWithMonitorTest(_RepoAgentChangedSignalTestBase):
| thgrepo.WorkingStateChanged)
class RepoAgentChangedSignalWithoutMonitorTest(_RepoAgentChangedSignalTestBase):
class RepoAgentChangedSignalWithoutMonitorTest(_RepoAgentChangedSignalTestBase, unittest.TestCase):
monitorrepo = b'never'
#!/usr/bin/env python
"""Run a set of tests by nosetests
"""Run a set of tests by pytest
To run all tests::
% export HGPATH=path/to/mercurial
% ./run-tests.py -a '!extensions' --with-doctest
% ./run-tests.py -a 'extensions=largefiles'
% ./run-tests.py -m 'not largefiles' --doctest-modules tests
% ./run-tests.py -m largefiles tests
For details, please see:
- `./run-tests.py --help`
- http://readthedocs.org/docs/nose/en/latest/
- https://docs.pytest.org/en/stable/
- http://docs.python.org/library/unittest.html
"""
import nose, os
import nosecaptureexc, nosehgenv
ignorefiles = [
r'^[._]',
r'^setup\.py$',
r'^TortoiseHgOverlayServer\.py$',
# exclude platform-dependent modules
r'^bugtraq\.py$',
r'^shellconf\.py$',
]
import sys
import pytest
import pytestcaptureexc, pytesthgenv
def main():
env = os.environ.copy()
if 'NOSE_IGNORE_FILES' not in env:
env['NOSE_IGNORE_FILES'] = ignorefiles
nose.main(env=env,
addplugins=[nosecaptureexc.CaptureExcPlugin(),
nosehgenv.HgEnvPlugin()])
sys.exit(pytest.main(plugins=[pytestcaptureexc.CaptureExcPlugin(),
pytesthgenv.HgEnvPlugin()]))
if __name__ == '__main__':
main()
import os, tempfile
from nose.tools import *
from nose.plugins.skip import SkipTest
from mercurial import (
config,
error,
pycompat,
)
import pytest
from tortoisehg.util import wconfig
import helpers
def setup():
def setup_module():
global _tempdir
_tempdir = helpers.mktmpdir(__name__)
......@@ -41,33 +41,40 @@ def writetempfile(s):
os.close(fd)
return path
class _Collector(list):
def __call__(self, func):
self.append(func)
return func
with_rconfig = _Collector()
with_wconfig = _Collector()
with_both = _Collector()
def with_rconfig(f):
f.__test__ = True
return pytest.mark.usefixtures('rconfig')(f)
def with_wconfig(f):
f.__test__ = True
return pytest.mark.usefixtures('wconfig')(f)
def test_both():
for e in with_wconfig + with_both:
if wconfig._hasiniparse:
yield e
else:
def skipped():
raise SkipTest
yield skipped
def with_both(f):
f.__test__ = True
return pytest.mark.usefixtures('both')(f)
@pytest.fixture(name='wconfig')
def fixture_wconfig():
if wconfig._hasiniparse:
yield
else:
pytest.skip()
@pytest.fixture(name='rconfig')
def fixture_rconfig():
orighasiniparse = wconfig._hasiniparse
wconfig._hasiniparse = False
try:
for e in with_rconfig + with_both:
yield e
yield
finally:
wconfig._hasiniparse = orighasiniparse
@pytest.fixture(name='both', params=['wconfig', 'rconfig'])
def fixture_both(request):
request.getfixturevalue(request.param)
@with_both
def check_copy():
......
......@@ -8,6 +8,6 @@ from tortoisehg.hgqt.qtgui import (
QApplication,
)
def setup():
def setup_module():
if not isinstance(QApplication.instance(), QApplication):
raise SkipTest
......@@ -16,7 +16,7 @@ from tortoisehg.hgqt import (
import helpers
def setup():
def setup_module():
global _tmpdir
_tmpdir = helpers.mktmpdir(__name__)
......
......@@ -161,9 +161,7 @@ class ArchiveWidget(cmdui.AbstractCmdWidget):
self.rev_combo.addItem(WD_PARENT)
self.rev_combo.addItems(pycompat.maplist(hglib.tounicode,
hglib.namedbranches(self.repo)))
tags = list(self.repo.tags())
tags.sort(reverse=True)
for t in tags:
for t in sorted(self.repo.tags(), reverse=True):
self.rev_combo.addItem(hglib.tounicode(t))
if rev:
text = hglib.tounicode(str(rev))
......
......@@ -256,6 +256,9 @@ def _proccmdline(ui, exts):
for section, name, value in ui.walkconfig()
if ui.configsource(section, name) == b'--config']
configs.extend(('extensions', e, '') for e in exts)
# Override user aliases (for example "alias.log=log --graph") that could
# break searching through the filter toolbar (CTRL+S).
configs.append(('alias', 'log', 'log'))
cmdline = list(paths.get_hg_command())
for section, name, value in configs:
cmdline.extend(('--config', '%s.%s=%s' % (section, name, value)))
......
......@@ -326,8 +326,8 @@ class CommitWidget(QWidget, qtlib.TaskWidget):
QSizePolicy.Preferred)
vbox.addWidget(self.optionslabel, 0)
self.pcsinfo = revpanel.ParentWidget(repo)
vbox.addWidget(self.pcsinfo, 0)
self.wdirinfo = revpanel.WDirInfoWidget(repo)
vbox.addWidget(self.wdirinfo, 0)
msgte = MessageEntry(self, self.stwidget.getChecked)
msgte.installEventFilter(qscilib.KeyPressInterceptor(self))
......@@ -551,9 +551,9 @@ class CommitWidget(QWidget, qtlib.TaskWidget):
self.stwidget.partials = {}
if refreshwctx:
self.stwidget.refreshWctx()
custom = self.pcsinfo.custom.copy()
custom = self.wdirinfo.custom.copy()
custom['isAmend'] = curraction._name == 'amend'
self.pcsinfo.update(custom=custom)
self.wdirinfo.update(custom=custom)
self.committb.setText(curraction._text)
self.lastAction = curraction._name
......@@ -781,18 +781,18 @@ class CommitWidget(QWidget, qtlib.TaskWidget):
False))
self.optionslabel.setVisible(bool(opts))