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 ...@@ -55,3 +55,4 @@ contrib/packaging/macos/toolchain/downloads
contrib/packaging/macos/toolchain/toolchain-qt4 contrib/packaging/macos/toolchain/toolchain-qt4
contrib/packaging/macos/toolchain/toolchain-qt5 contrib/packaging/macos/toolchain/toolchain-qt5
contrib/packaging/macos/releases contrib/packaging/macos/releases
.pytest_cache
...@@ -32,8 +32,8 @@ local: ...@@ -32,8 +32,8 @@ local:
tests: tests:
@[ -n "$(HGPATH)" ] || { echo "HGPATH not specified"; false; } @[ -n "$(HGPATH)" ] || { echo "HGPATH not specified"; false; }
@[ -d "$(HGPATH)" ] || { echo "HGPATH not found: $(HGPATH)"; false; } @[ -d "$(HGPATH)" ] || { echo "HGPATH not found: $(HGPATH)"; false; }
$(PYTHON) tests/run-tests.py -a '!extensions' --with-doctest $(PYTHON) tests/run-tests.py -m 'not largefiles' --doctest-modules tests
$(PYTHON) tests/run-tests.py -a extensions=largefiles $(PYTHON) tests/run-tests.py -m largefiles tests
$(PYTHON) tests/run-hgtests.py $(PYTHON) tests/run-hgtests.py
.PHONY: pytype .PHONY: pytype
......
...@@ -3,12 +3,12 @@ import sys ...@@ -3,12 +3,12 @@ import sys
from nose.tools import * from nose.tools import *
from tortoisehg.util import colormap from tortoisehg.util import colormap
def setup(): def setup_module():
global _origmaxint global _origmaxint
_origmaxint = sys.maxsize _origmaxint = sys.maxsize
sys.maxsize = int((1 << 31) - 1) sys.maxsize = int((1 << 31) - 1)
def teardown(): def teardown_module():
sys.maxsize = _origmaxint sys.maxsize = _origmaxint
def fakectx(userhash, date, tz=0): def fakectx(userhash, date, tz=0):
......
import functools
import os import os
from nose.tools import * from nose.tools import *
import pytest
from tortoisehg.hgqt import filedata, thgrepo from tortoisehg.hgqt import filedata, thgrepo
import helpers import helpers
def setup(): def setup_module():
global _tmpdir global _tmpdir
_tmpdir = helpers.mktmpdir(__name__) _tmpdir = helpers.mktmpdir(__name__)
...@@ -40,30 +42,32 @@ def loaddata(reponame, rev, path, prev=None): ...@@ -40,30 +42,32 @@ def loaddata(reponame, rev, path, prev=None):
return fd 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) assert message in fd.error, (message, fd.error)
# no data should be loaded # no data should be loaded
assert_false(fd.contents) assert_false(fd.contents)
assert_false(fd.olddata) assert_false(fd.olddata)
assert_false(fd.diff) 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): def check_flabel(fd, message):
assert message in fd.flabel, (message, fd.flabel) assert message in fd.flabel, (message, fd.flabel)
def test_flabel_added(): @pytest.mark.parametrize('get_fd, message', [
for path in ['text', 'binary', 'text-over1kb']: (functools.partial(loaddata, 'status', rev, path + sfx), msg)
for path in ['text', 'binary', 'text-over1kb']
for rev, sfx, msg in [(0, '', 'added'), for rev, sfx, msg in [(0, '', 'added'),
(1, '.copied', 'copied from'), (1, '.copied', 'copied from'),
(2, '.renamed', 'renamed from')]: (2, '.renamed', 'renamed from')]
fd = loaddata('status', rev, path + sfx) ])
yield check_flabel, fd, msg def test_flabel_added(get_fd, message):
check_flabel(get_fd(), message)
def test_flabel_far_rename(): def test_flabel_far_rename():
fd = loaddata('status', 2, 'text.copied', 0) fd = loaddata('status', 2, 'text.copied', 0)
......
...@@ -10,7 +10,7 @@ from tortoisehg.util import hglib ...@@ -10,7 +10,7 @@ from tortoisehg.util import hglib
import helpers import helpers
def setup(): def setup_module():
global _tmpdir global _tmpdir
_tmpdir = helpers.mktmpdir(__name__) _tmpdir = helpers.mktmpdir(__name__)
......
...@@ -8,7 +8,7 @@ from tortoisehg.util import hglib ...@@ -8,7 +8,7 @@ from tortoisehg.util import hglib
import helpers import helpers
def setup(): def setup_module():
global _tmpdir global _tmpdir
_tmpdir = helpers.mktmpdir(__name__) _tmpdir = helpers.mktmpdir(__name__)
......
...@@ -2,13 +2,14 @@ ...@@ -2,13 +2,14 @@
import os import os
from nose.tools import * from nose.tools import *
import pytest
from mercurial import hg from mercurial import hg
from tortoisehg.util import hglib from tortoisehg.util import hglib
import helpers import helpers
def setup(): def setup_module():
global _tmpdir global _tmpdir
_tmpdir = helpers.mktmpdir(__name__) _tmpdir = helpers.mktmpdir(__name__)
...@@ -44,15 +45,14 @@ def setup_repoid(): ...@@ -44,15 +45,14 @@ def setup_repoid():
hg = helpers.HgClient(os.path.join(_tmpdir, 'repoid-rev0hidden')) hg = helpers.HgClient(os.path.join(_tmpdir, 'repoid-rev0hidden'))
hg.debugobsolete(_repoidnodes[0]) 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) repo = openrepo(reponame)
nodehex = _repoidnodes[rootrev] nodehex = _repoidnodes[rootrev]
assert_equal(nodehex[:12], hglib.shortrepoid(repo)) assert_equal(nodehex[:12], hglib.shortrepoid(repo))
assert_equal(nodehex.decode('hex'), hglib.repoidnode(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""" """Test for compatibility with Mercurial API"""
import inspect import inspect
import pytest
from nose.tools import * from nose.tools import *
from tortoisehg.util import hglib, pipeui 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) fa, ga = inspect.getargspec(f), inspect.getargspec(g)
assert_equals(fa, ga, assert_equals(fa, ga,
'%s != %s' % (inspect.formatargspec(*fa), '%s != %s' % (inspect.formatargspec(*fa),
...@@ -13,13 +15,13 @@ def assert_same_argspec(f, g): ...@@ -13,13 +15,13 @@ def assert_same_argspec(f, g):
def overridden_methods(cls): def overridden_methods(cls):
basemethods = inspect.getmembers(cls.__base__, inspect.ismethod) basemethods = inspect.getmembers(cls.__base__, inspect.ismethod)
return [(name, basemeth, getattr(cls, name)) return [(basemeth, getattr(cls, name))
for name, basemeth in basemethods for name, basemeth in basemethods
if basemeth.__func__ is not getattr(cls, name).__func__] if basemeth.__func__ is not getattr(cls, name).__func__]
def test_pipeui(): def pytest_generate_tests(metafunc):
ui = hglib.loadui() ui = hglib.loadui()
pipeui.uisetup(ui) pipeui.uisetup(ui)
for name, basemeth, meth in overridden_methods(ui.__class__): if metafunc.function == test_same_argspec:
yield assert_same_argspec, basemeth, meth 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 from __future__ import absolute_import
...@@ -7,27 +7,28 @@ import shutil ...@@ -7,27 +7,28 @@ import shutil
import sys import sys
import tempfile import tempfile
from nose import plugins import pytest
# don't import mercurial or tortoisehg before setting up test environment # don't import mercurial or tortoisehg before setting up test environment
class HgEnvPlugin(plugins.Plugin): class HgEnvPlugin(object):
"""Set up temporary environment""" """Set up temporary environment"""
enabled = True
name = 'hgenv'
def options(self, parser, env): def pytest_addoption(self, parser):
parser.add_option('--keep-tmpdir', action='store_true', default=False, parser.addoption('--keep-tmpdir', action='store_true', default=False,
help='Keep temporary directory after running tests') help='Keep temporary directory after running tests')
parser.add_option('--tmpdir', parser.addoption('--tmpdir',
help=('Put temporary files in the given directory ' help=('Put temporary files in the given directory '
'(implies --keep-tmpdir)')) '(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.keep_tmpdir = options.keep_tmpdir or bool(options.tmpdir)
self.tmpdir = options.tmpdir self.tmpdir = options.tmpdir
def begin(self): @pytest.hookimpl(tryfirst=True)
def pytest_collection(self):
if 'mercurial' in sys.modules: if 'mercurial' in sys.modules:
raise Exception('loaded mercurial module before setting up ' raise Exception('loaded mercurial module before setting up '
'test environment') 'test environment')
...@@ -124,7 +125,7 @@ class HgEnvPlugin(plugins.Plugin): ...@@ -124,7 +125,7 @@ class HgEnvPlugin(plugins.Plugin):
QSettings.setPath(QSettings.IniFormat, QSettings.UserScope, QSettings.setPath(QSettings.IniFormat, QSettings.UserScope,
self.configdir) self.configdir)
def finalize(self, result): def pytest_sessionfinish(self):
del self._qapp del self._qapp
if not self.keep_tmpdir: if not self.keep_tmpdir:
......
...@@ -55,7 +55,7 @@ def waitForCmdStarted(session, timeout=5000): ...@@ -55,7 +55,7 @@ def waitForCmdStarted(session, timeout=5000):
loop.exec_() loop.exec_()
class _CmdAgentTestBase(unittest.TestCase): class _CmdAgentTestBase(object):
@classmethod @classmethod
def setUpClass(cls): def setUpClass(cls):
tmpdir = helpers.mktmpdir(cls.__name__) tmpdir = helpers.mktmpdir(cls.__name__)
...@@ -247,11 +247,11 @@ class _CmdAgentTestBase(unittest.TestCase): ...@@ -247,11 +247,11 @@ class _CmdAgentTestBase(unittest.TestCase):
self.assertFalse(self.agent.isBusy()) self.assertFalse(self.agent.isBusy())
class CmdAgentProcTest(_CmdAgentTestBase): class CmdAgentProcTest(_CmdAgentTestBase, unittest.TestCase):
workername = 'proc' workername = 'proc'
class CmdAgentServerTest(_CmdAgentTestBase): class CmdAgentServerTest(_CmdAgentTestBase, unittest.TestCase):
workername = 'server' workername = 'server'
@classmethod @classmethod
......
...@@ -11,6 +11,8 @@ from mercurial import ( ...@@ -11,6 +11,8 @@ from mercurial import (
from nose.plugins.skip import SkipTest from nose.plugins.skip import SkipTest
import pytest
from tortoisehg.hgqt.qtcore import ( from tortoisehg.hgqt.qtcore import (
QModelIndex, QModelIndex,
Qt, Qt,
...@@ -27,7 +29,7 @@ from tortoisehg.hgqt.manifestmodel import ManifestModel ...@@ -27,7 +29,7 @@ from tortoisehg.hgqt.manifestmodel import ManifestModel
import helpers import helpers
def setup(): def setup_module():
# necessary for style().standardIcon() # necessary for style().standardIcon()
if not isinstance(QApplication.instance(), QApplication): if not isinstance(QApplication.instance(), QApplication):
raise SkipTest raise SkipTest
...@@ -637,9 +639,8 @@ class ManifestModelReloadTest(unittest.TestCase): ...@@ -637,9 +639,8 @@ class ManifestModelReloadTest(unittest.TestCase):
self.assertEqual(['bar', 'foo'], alldata(m)) self.assertEqual(['bar', 'foo'], alldata(m))
@pytest.mark.largefiles
class ManifestModelLargeFilesTest(unittest.TestCase): class ManifestModelLargeFilesTest(unittest.TestCase):
extensions = ['largefiles']
@classmethod @classmethod
def setUpClass(cls): def setUpClass(cls):
cls.hg = hg = helpers.HgClient(os.path.join(_tmpdir, cls.__name__)) cls.hg = hg = helpers.HgClient(os.path.join(_tmpdir, cls.__name__))
......
...@@ -50,7 +50,7 @@ class RepoAgentAttributeTest(unittest.TestCase): ...@@ -50,7 +50,7 @@ class RepoAgentAttributeTest(unittest.TestCase):
self.assertFalse(self.agent.hiddenRevsIncluded()) self.assertFalse(self.agent.hiddenRevsIncluded())
class _RepoAgentChangedSignalTestBase(unittest.TestCase): class _RepoAgentChangedSignalTestBase(object):
@classmethod @classmethod
def setUpClass(cls): def setUpClass(cls):
tmpdir = helpers.mktmpdir(cls.__name__) tmpdir = helpers.mktmpdir(cls.__name__)
...@@ -198,7 +198,7 @@ class _RepoAgentChangedSignalTestBase(unittest.TestCase): ...@@ -198,7 +198,7 @@ class _RepoAgentChangedSignalTestBase(unittest.TestCase):
self.wait_changed(thgrepo.LogChanged) self.wait_changed(thgrepo.LogChanged)
class RepoAgentChangedSignalWithMonitorTest(_RepoAgentChangedSignalTestBase): class RepoAgentChangedSignalWithMonitorTest(_RepoAgentChangedSignalTestBase, unittest.TestCase):
monitorrepo = b'always' monitorrepo = b'always'
def test_filesystem_watcher(self): def test_filesystem_watcher(self):
...@@ -225,5 +225,5 @@ class RepoAgentChangedSignalWithMonitorTest(_RepoAgentChangedSignalTestBase): ...@@ -225,5 +225,5 @@ class RepoAgentChangedSignalWithMonitorTest(_RepoAgentChangedSignalTestBase):
| thgrepo.WorkingStateChanged) | thgrepo.WorkingStateChanged)
class RepoAgentChangedSignalWithoutMonitorTest(_RepoAgentChangedSignalTestBase): class RepoAgentChangedSignalWithoutMonitorTest(_RepoAgentChangedSignalTestBase, unittest.TestCase):
monitorrepo = b'never' monitorrepo = b'never'
#!/usr/bin/env python #!/usr/bin/env python
"""Run a set of tests by nosetests """Run a set of tests by pytest
To run all tests:: To run all tests::
% export HGPATH=path/to/mercurial % export HGPATH=path/to/mercurial
% ./run-tests.py -a '!extensions' --with-doctest % ./run-tests.py -m 'not largefiles' --doctest-modules tests
% ./run-tests.py -a 'extensions=largefiles' % ./run-tests.py -m largefiles tests
For details, please see: For details, please see:
- `./run-tests.py --help` - `./run-tests.py --help`
- http://readthedocs.org/docs/nose/en/latest/ - https://docs.pytest.org/en/stable/
- http://docs.python.org/library/unittest.html - http://docs.python.org/library/unittest.html
""" """
import nose, os import sys
import pytest
import nosecaptureexc, nosehgenv import pytestcaptureexc, pytesthgenv
ignorefiles = [
r'^[._]',
r'^setup\.py$',
r'^TortoiseHgOverlayServer\.py$',
# exclude platform-dependent modules
r'^bugtraq\.py$',
r'^shellconf\.py$',
]
def main(): def main():
env = os.environ.copy() sys.exit(pytest.main(plugins=[pytestcaptureexc.CaptureExcPlugin(),
if 'NOSE_IGNORE_FILES' not in env: pytesthgenv.HgEnvPlugin()]))
env['NOSE_IGNORE_FILES'] = ignorefiles
nose.main(env=env,
addplugins=[nosecaptureexc.CaptureExcPlugin(),
nosehgenv.HgEnvPlugin()])
if __name__ == '__main__': if __name__ == '__main__':
main() main()
import os, tempfile import os, tempfile
from nose.tools import * from nose.tools import *
from nose.plugins.skip import SkipTest