Commit 74bed1d4 authored by Jason Madden's avatar Jason Madden

Move rest of config out of testrunner, and test more modules in execmodules and __all__.

parent 2545c60c
# -*- coding: utf-8 -*-
from __future__ import absolute_import
from __future__ import division
from __future__ import print_function
# Nothing public here
__all__ = []
......@@ -5,6 +5,10 @@ import sys
from gevent.libev import _corecffi # pylint:disable=no-name-in-module,import-error
# Nothing public here
__all__ = []
ffi = _corecffi.ffi # pylint:disable=no-member
libev = _corecffi.lib # pylint:disable=no-member
......
# -*- coding: utf-8 -*-
from __future__ import absolute_import
from __future__ import division
from __future__ import print_function
# Nothing public here
__all__ = []
......@@ -7,6 +7,9 @@ import sys
from gevent.libuv import _corecffi # pylint:disable=no-name-in-module,import-error
# Nothing public here
__all__ = []
ffi = _corecffi.ffi
libuv = _corecffi.lib
......
......@@ -16,6 +16,8 @@ from gevent.socket import EAI_SERVICE
from gevent.socket import AF_INET
from gevent.socket import AI_PASSIVE
# Nothing public here.
__all__ = []
def _lookup_port(port, socktype):
# pylint:disable=too-many-branches
......
......@@ -2,6 +2,10 @@
import _socket
__all__ = [
'Resolver',
]
class Resolver(object):
"""
A resolver that directly uses the system's resolver functions.
......
......@@ -75,8 +75,8 @@ from _socket import AF_UNSPEC
import socket
from . import AbstractResolver
from . import hostname_types
from gevent.resolver import AbstractResolver
from gevent.resolver import hostname_types
from gevent._compat import string_types
from gevent._compat import iteritems
......
......@@ -7,7 +7,8 @@ import warnings
warnings.warn(
"gevent.resolver_ares is deprecated and will be removed in 1.5. "
"Use gevent.resolver.ares instead.",
DeprecationWarning
DeprecationWarning,
stacklevel=2
)
del warnings
from gevent.resolver.ares import * # pylint:disable=wildcard-import,unused-wildcard-import
......
......@@ -7,7 +7,8 @@ import warnings
warnings.warn(
"gevent.resolver_thread is deprecated and will be removed in 1.5. "
"Use gevent.resolver.thread instead.",
DeprecationWarning
DeprecationWarning,
stacklevel=2
)
del warnings
from gevent.resolver.thread import * # pylint:disable=wildcard-import,unused-wildcard-import
......
......@@ -19,12 +19,14 @@
# THE SOFTWARE.
from __future__ import absolute_import, print_function, division
import importlib
import os.path
import warnings
import gevent
from . import sysinfo
from . import six
OPTIONAL_MODULES = ['resolver_ares']
......@@ -45,6 +47,8 @@ def walk_modules(basedir=None, modpath=None, include_so=False, recursive=False):
if os.path.isdir(path):
if not recursive:
continue
if fn in ['testing', 'tests']:
continue
pkg_init = os.path.join(path, '__init__.py')
if os.path.exists(pkg_init):
yield pkg_init, modpath + fn
......@@ -60,7 +64,9 @@ def walk_modules(basedir=None, modpath=None, include_so=False, recursive=False):
continue
if x in OPTIONAL_MODULES:
try:
six.exec_("import %s" % x, {})
with warnings.catch_warnings():
warnings.simplefilter('ignore', DeprecationWarning)
importlib.import_module(modpath + x)
except ImportError:
continue
yield path, modpath + x
......
......@@ -49,9 +49,9 @@ RUN_COVERAGE = os.getenv("COVERAGE_PROCESS_START") or os.getenv("GEVENTTEST_COVE
# Generally, ignore the portions that are only implemented
# on particular platforms; they generally contain partial
# implementations completed in different modules.
PLATFORM_SPECIFIC_SUFFIXES = ['2', '279', '3']
PLATFORM_SPECIFIC_SUFFIXES = ('2', '279', '3')
if WIN:
PLATFORM_SPECIFIC_SUFFIXES.append('posix')
PLATFORM_SPECIFIC_SUFFIXES += ('posix',)
PY2 = None
PY3 = None
......
......@@ -15,10 +15,8 @@ from . import util
from .util import log
from .sysinfo import RUNNING_ON_CI
from .sysinfo import PYPY
from .sysinfo import PY3
from .sysinfo import PY2
from .sysinfo import RESOLVER_ARES
from .sysinfo import LIBUV
from .sysinfo import RUN_LEAKCHECKS
from . import six
......@@ -45,72 +43,13 @@ DEFAULT_RUN_OPTIONS = {
'timeout': TIMEOUT
}
# A mapping from test file basename to a dictionary of
# options that will be applied on top of the DEFAULT_RUN_OPTIONS.
TEST_FILE_OPTIONS = {
}
if RUNNING_ON_CI:
# Too many and we get spurious timeouts
NWORKERS = 4
# tests that don't do well when run on busy box
RUN_ALONE = [
'test__threadpool.py',
'test__examples.py',
]
if RUNNING_ON_CI:
RUN_ALONE += [
# Partial workaround for the _testcapi issue on PyPy,
# but also because signal delivery can sometimes be slow, and this
# spawn processes of its own
'test_signal.py',
]
if RUN_LEAKCHECKS and PY3:
# On a heavily loaded box, these can all take upwards of 200s
RUN_ALONE += [
'test__pool.py',
'test__pywsgi.py',
'test__queue.py',
]
if PYPY:
# This often takes much longer on PyPy on CI.
TEST_FILE_OPTIONS['test__threadpool.py'] = {'timeout': 180}
if PY3:
RUN_ALONE += [
# Sometimes shows unexpected timeouts
'test_socket.py',
]
if LIBUV:
RUN_ALONE += [
# https://bitbucket.org/pypy/pypy/issues/2769/systemerror-unexpected-internal-exception
'test__pywsgi.py',
]
# tests that can't be run when coverage is enabled
IGNORE_COVERAGE = [
# Hangs forever
'test__threading_vs_settrace.py',
# times out
'test_socket.py',
# Doesn't get the exceptions it expects
'test_selectors.py',
# XXX ?
'test__issue302monkey.py',
"test_subprocess.py",
]
if PYPY:
IGNORE_COVERAGE += [
# Tends to timeout
'test__refcount.py',
'test__greenletset.py'
]
def _package_relative_filename(filename, package):
if not os.path.isfile(filename) and package:
......@@ -125,7 +64,11 @@ def _dir_from_package_name(package):
return package_dir
def run_many(tests, configured_failing_tests=(), failfast=False, quiet=False):
def run_many(tests,
configured_failing_tests=(),
failfast=False,
quiet=False,
configured_run_alone_tests=()):
# pylint:disable=too-many-locals,too-many-statements
global NWORKERS
start = time.time()
......@@ -182,7 +125,7 @@ def run_many(tests, configured_failing_tests=(), failfast=False, quiet=False):
for cmd, options in tests:
total += 1
options = options or {}
if matches(RUN_ALONE, cmd):
if matches(configured_run_alone_tests, cmd):
run_alone.append((cmd, options))
else:
spawn(cmd, options)
......@@ -212,10 +155,15 @@ def run_many(tests, configured_failing_tests=(), failfast=False, quiet=False):
report(total, failed, passed, took=time.time() - start,
configured_failing_tests=configured_failing_tests)
def discover(tests=None, ignore_files=None,
ignored=(), coverage=False,
package=None):
def discover(
tests=None, ignore_files=None,
ignored=(), coverage=False,
package=None,
configured_ignore_coverage=(),
configured_test_options=None,
):
# pylint:disable=too-many-locals,too-many-branches
configured_test_options = configured_test_options or {}
olddir = os.getcwd()
ignore = set(ignored or ())
......@@ -225,7 +173,7 @@ def discover(tests=None, ignore_files=None,
ignore.update(set(load_list_from_file(f, package)))
if coverage:
ignore.update(IGNORE_COVERAGE)
ignore.update(configured_ignore_coverage)
if package:
package_dir = _dir_from_package_name(package)
......@@ -280,7 +228,7 @@ def discover(tests=None, ignore_files=None,
cmd.append(filename)
options = DEFAULT_RUN_OPTIONS.copy()
options.update(TEST_FILE_OPTIONS.get(filename, {}))
options.update(configured_test_options.get(filename, {}))
to_process.append((cmd, options))
os.chdir(olddir)
......@@ -429,6 +377,7 @@ def _setup_environ(debug=False):
def main():
# pylint:disable=too-many-locals,too-many-statements
import argparse
parser = argparse.ArgumentParser()
parser.add_argument('--ignore')
......@@ -445,6 +394,9 @@ def main():
options = parser.parse_args()
FAILING_TESTS = []
IGNORED_TESTS = []
RUN_ALONE = []
TEST_FILE_OPTIONS = {}
coverage = False
if options.coverage or os.environ.get("GEVENTTEST_COVERAGE"):
coverage = True
......@@ -471,14 +423,20 @@ def main():
six.exec_(config_data, config)
FAILING_TESTS = config['FAILING_TESTS']
IGNORED_TESTS = config['IGNORED_TESTS']
tests = discover(options.tests,
ignore_files=options.ignore,
ignored=IGNORED_TESTS,
coverage=coverage,
package=options.package)
RUN_ALONE = config['RUN_ALONE']
TEST_FILE_OPTIONS = config['TEST_FILE_OPTIONS']
IGNORE_COVERAGE = config['IGNORE_COVERAGE']
tests = discover(
options.tests,
ignore_files=options.ignore,
ignored=IGNORED_TESTS,
coverage=coverage,
package=options.package,
configured_ignore_coverage=IGNORE_COVERAGE,
configured_test_options=TEST_FILE_OPTIONS,
)
if options.discover:
for cmd, options in tests:
print(util.getname(cmd, env=options.get('env'), setenv=options.get('setenv')))
......@@ -492,7 +450,13 @@ def main():
# Put this directory on the path so relative imports work.
package_dir = _dir_from_package_name(options.package)
os.environ['PYTHONPATH'] = os.environ.get('PYTHONPATH', "") + os.pathsep + package_dir
run_many(tests, configured_failing_tests=FAILING_TESTS, failfast=options.failfast, quiet=options.quiet)
run_many(
tests,
configured_failing_tests=FAILING_TESTS,
failfast=options.failfast,
quiet=options.quiet,
configured_run_alone_tests=RUN_ALONE,
)
if __name__ == '__main__':
......
......@@ -262,5 +262,71 @@ if COVERAGE:
FAILING_TESTS = [x.strip() for x in set(FAILING_TESTS) if x.strip()]
# A mapping from test file basename to a dictionary of
# options that will be applied on top of the DEFAULT_RUN_OPTIONS.
TEST_FILE_OPTIONS = {
}
# tests that don't do well when run on busy box
RUN_ALONE = [
'test__threadpool.py',
'test__examples.py',
]
if APPVEYOR or TRAVIS:
RUN_ALONE += [
# Partial workaround for the _testcapi issue on PyPy,
# but also because signal delivery can sometimes be slow, and this
# spawn processes of its own
'test_signal.py',
]
if LEAKTEST and PY3:
# On a heavily loaded box, these can all take upwards of 200s
RUN_ALONE += [
'test__pool.py',
'test__pywsgi.py',
'test__queue.py',
]
if PYPY:
# This often takes much longer on PyPy on CI.
TEST_FILE_OPTIONS['test__threadpool.py'] = {'timeout': 180}
TEST_FILE_OPTIONS['test__threading_2.py'] = {'timeout': 180}
if PY3:
RUN_ALONE += [
# Sometimes shows unexpected timeouts
'test_socket.py',
]
if LIBUV:
RUN_ALONE += [
# https://bitbucket.org/pypy/pypy/issues/2769/systemerror-unexpected-internal-exception
'test__pywsgi.py',
]
# tests that can't be run when coverage is enabled
IGNORE_COVERAGE = [
# Hangs forever
'test__threading_vs_settrace.py',
# times out
'test_socket.py',
# Doesn't get the exceptions it expects
'test_selectors.py',
# XXX ?
'test__issue302monkey.py',
"test_subprocess.py",
]
if PYPY:
IGNORE_COVERAGE += [
# Tends to timeout
'test__refcount.py',
'test__greenletset.py'
]
if __name__ == '__main__':
print('known_failures:\n', FAILING_TESTS)
"""Check __all__, __implements__, __extensions__, __imports__ of the modules"""
from __future__ import print_function
from gevent.testing import six
import sys
import unittest
import types
import importlib
import warnings
from gevent.testing import six
from gevent.testing.modules import walk_modules
from gevent.testing.sysinfo import PLATFORM_SPECIFIC_SUFFIXES
......@@ -30,7 +34,9 @@ COULD_BE_MISSING = {
'subprocess': ['_posixsubprocess'],
}
NO_ALL = [
# Things without an __all__ should generally be internal implementation
# helpers
NO_ALL = {
'gevent.threading',
'gevent._util',
'gevent._compat',
......@@ -40,7 +46,8 @@ NO_ALL = [
'gevent._tblib',
'gevent._corecffi',
'gevent._patcher',
]
'gevent._ffi',
}
ALLOW_IMPLEMENTS = [
'gevent._queue',
......@@ -175,13 +182,13 @@ are missing from %r:
raise AssertionError(msg)
def _test(self, modname):
for x in PLATFORM_SPECIFIC_SUFFIXES:
if modname.endswith(x):
return
if modname.endswith(PLATFORM_SPECIFIC_SUFFIXES):
return
self.modname = modname
six.exec_("import %s" % modname, {})
self.module = sys.modules[modname]
with warnings.catch_warnings():
warnings.simplefilter('ignore', DeprecationWarning)
self.module = importlib.import_module(modname)
self.check_all()
......@@ -216,14 +223,17 @@ are missing from %r:
path = modname = orig_modname = None
for path, modname in walk_modules(include_so=True):
for path, modname in walk_modules(include_so=False, recursive=True):
orig_modname = modname
modname = modname.replace('gevent.', '').split('.')[0]
if not modname:
print("WARNING: No such module '%s' at '%s'" % (orig_modname, path),
file=sys.stderr)
continue
exec('''def test_%s(self): self._test("gevent.%s")''' % (modname, modname))
exec(
'''def test_%s(self): self._test("%s")''' % (
orig_modname.replace('.', '_').replace('-', '_'), orig_modname)
)
del path, modname, orig_modname
......
import unittest
import warnings
from gevent.testing.modules import walk_modules
from gevent.testing import main
......@@ -15,17 +16,18 @@ class TestExec(unittest.TestCase):
def make_exec_test(path, module):
def test(_):
#sys.stderr.write('%s %s\n' % (module, path))
with open(path, 'rb') as f:
src = f.read()
six.exec_(src, {'__file__': path})
with warnings.catch_warnings():
warnings.simplefilter('ignore', DeprecationWarning)
six.exec_(src, {'__file__': path})
name = "test_" + module.replace(".", "_")
test.__name__ = name
setattr(TestExec, name, test)
def make_all_tests():
for path, module in walk_modules():
for path, module in walk_modules(recursive=True):
if module.endswith(NON_APPLICABLE_SUFFIXES):
continue
make_exec_test(path, module)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment