Commit a2c56938 authored by Jason Madden's avatar Jason Madden Committed by GitHub

Merge pull request #1309 from gevent/issue1293

Refactoring greentest
parents a8c1f171 b77e9acd
......@@ -12,12 +12,11 @@ omit =
src/gevent/_ssl2.py
src/gevent/libev/_corecffi_build.py
src/gevent/libuv/_corecffi_build.py
src/gevent/win32util.py
src/gevent/win32util.py
# having concurrency=greenlet means that the Queue class
# which is used from multiple real threads doesn't
# properly get covered.
src/gevent/_threading.py
test_*
src/gevent/_threading.py
# local.so sometimes gets included, and it can't be parsed
# as source, so it fails the whole process.
*.so
......@@ -43,3 +42,4 @@ omit =
# as source, so it fails the whole process.
# coverage 4.5 needs this specified here, 4.4.2 needed it in [run]
*.so
/tmp/test_*
......@@ -35,9 +35,9 @@ Makefile.ext
MANIFEST
*_flymake.py
src/greentest/.coverage\.*
src/greentest/htmlcov
src/greentest/.coverage
.coverage\.*
htmlcov/
.coverage
doc/_build
doc/__pycache__
......
......@@ -98,7 +98,7 @@ ignored-classes=SSLContext, SSLSocket, greenlet, Greenlet, parent, dead
# (useful for modules/projects where namespaces are manipulated during runtime
# and thus existing member attributes cannot be deduced by static analysis. It
# supports qualified module names, as well as Unix pattern matching.
ignored-modules=gevent._corecffi,gevent.os,os,greenlet,threading,gevent.libev.corecffi
ignored-modules=gevent._corecffi,gevent.os,os,greenlet,threading,gevent.libev.corecffi,gevent.socket,gevent.core
[DESIGN]
max-attributes=12
......
......@@ -9,6 +9,11 @@ env:
global:
- BUILD_RUNTIMES=$HOME/.runtimes
- PYTHONHASHSEED=random
- CC="ccache gcc"
- CCACHE_NOCPP2=true
- CCACHE_SLOPPINESS=file_macro,time_macros,include_file_ctime,include_file_mtime
- CCACHE_NOHASHDIR=true
- CFLAGS="-g -pipe"
matrix:
# These are ordered to get as much diversity in the
......@@ -38,7 +43,7 @@ cache:
- $HOME/.venv
- $HOME/.runtimes
- $HOME/.wheelhouse
- $HOME/.ccache
before_cache:
- rm -f $HOME/.cache/pip/log/debug.log
......@@ -42,6 +42,10 @@
Objects/tupleobject.c: bad argument to internal function``. Reported
in :issue:`1302` by Ulrich Petri.
- Refactored the gevent test runner and test suite to make them more
reusable. In particular, the tests are now run with ``python -m
gevent.tests``. See :issue:`1293`.
1.3.7 (2018-10-12)
==================
......
......@@ -22,7 +22,7 @@ clean:
rm -rf src/gevent/libev/*.o src/gevent/libuv/*.o src/gevent/*.o
rm -rf src/gevent/__pycache__ src/greentest/__pycache__ src/greentest/greentest/__pycache__ src/gevent/libev/__pycache__
rm -rf src/gevent/*.pyc src/greentest/*.pyc src/gevent/libev/*.pyc
rm -rf src/greentest/htmlcov src/greentest/.coverage
rm -rf htmlcov .coverage
rm -rf build
distclean: clean
......@@ -33,8 +33,6 @@ distclean: clean
doc:
cd doc && PYTHONPATH=.. make html
whitespace:
! find . -not -path "*.pem" -not -path "./.eggs/*" -not -path "./src/greentest/htmlcov/*" -not -path "./src/greentest/.coverage.*" -not -path "./.tox/*" -not -path "*/__pycache__/*" -not -path "*.so" -not -path "*.pyc" -not -path "./.git/*" -not -path "./build/*" -not -path "./src/gevent/libev/*" -not -path "./src/gevent.egg-info/*" -not -path "./dist/*" -not -path "./.DS_Store" -not -path "./deps/*" -not -path "./src/gevent/libev/corecext.*.[ch]" -not -path "./src/gevent/resolver/cares.*" -not -path "./doc/_build/*" -not -path "./doc/mytheme/static/*" -type f | xargs egrep -l " $$"
prospector:
which pylint
......@@ -59,28 +57,25 @@ test_prelim:
basictest: test_prelim
@${PYTHON} scripts/travis.py fold_start basictest "Running basic tests"
cd src/greentest && GEVENT_RESOLVER=thread ${PYTHON} testrunner.py --config known_failures.py --quiet
GEVENT_RESOLVER=thread ${PYTHON} -mgevent.tests --config known_failures.py --quiet
@${PYTHON} scripts/travis.py fold_end basictest
alltest: basictest
@${PYTHON} scripts/travis.py fold_start ares "Running c-ares tests"
cd src/greentest && GEVENT_RESOLVER=ares ${PYTHON} testrunner.py --config known_failures.py --ignore tests_that_dont_use_resolver.txt --quiet
GEVENT_RESOLVER=ares ${PYTHON} -mgevent.tests --config known_failures.py --ignore tests_that_dont_use_resolver.txt --quiet
@${PYTHON} scripts/travis.py fold_end ares
@${PYTHON} scripts/travis.py fold_start dnspython "Running dnspython tests"
cd src/greentest && GEVENT_RESOLVER=dnspython ${PYTHON} testrunner.py --config known_failures.py --ignore tests_that_dont_use_resolver.txt --quiet
GEVENT_RESOLVER=dnspython ${PYTHON} -mgevent.tests --config known_failures.py --ignore tests_that_dont_use_resolver.txt --quiet
@${PYTHON} scripts/travis.py fold_end dnspython
# In the past, we included all test files that had a reference to 'subprocess'' somewhere in their
# text. The monkey-patched stdlib tests were specifically included here.
# However, we now always also test on AppVeyor (Windows) which only has GEVENT_FILE=thread,
# so we can save a lot of CI time by reducing the set and excluding the stdlib tests without
# losing any coverage. See the `threadfiletest` for what command used to run.
# losing any coverage.
@${PYTHON} scripts/travis.py fold_start thread "Running GEVENT_FILE=thread tests"
cd src/greentest && GEVENT_FILE=thread ${PYTHON} testrunner.py --config known_failures.py test__*subprocess*.py --quiet
cd src/gevent/tests && GEVENT_FILE=thread ${PYTHON} -mgevent.tests --config known_failures.py test__*subprocess*.py --quiet
@${PYTHON} scripts/travis.py fold_end thread
threadfiletest:
cd src/greentest && GEVENT_FILE=thread ${PYTHON} testrunner.py --config known_failures.py `grep -l subprocess test_*.py` --quiet
allbackendtest:
@${PYTHON} scripts/travis.py fold_start default "Testing default backend"
GEVENTTEST_COVERAGE=1 make alltest
......@@ -101,7 +96,7 @@ cffibackendtest:
leaktest: test_prelim
@${PYTHON} scripts/travis.py fold_start leaktest "Running leak tests"
cd src/greentest && GEVENT_RESOLVER=thread GEVENTTEST_LEAKCHECK=1 ${PYTHON} testrunner.py --config known_failures.py --quiet --ignore tests_that_dont_do_leakchecks.txt
GEVENT_RESOLVER=thread GEVENTTEST_LEAKCHECK=1 ${PYTHON} -mgevent.tests --config known_failures.py --quiet --ignore tests_that_dont_do_leakchecks.txt
@${PYTHON} scripts/travis.py fold_end leaktest
@${PYTHON} scripts/travis.py fold_start default "Testing default backend pure python"
PURE_PYTHON=1 GEVENTTEST_COVERAGE=1 make basictest
......@@ -116,8 +111,9 @@ travis_test_linters:
make cffibackendtest
coverage_combine:
coverage combine . src/greentest/
-coveralls --rcfile=src/greentest/.coveragerc
coverage combine .
coverage report -i
-coveralls
.PHONY: clean doc prospector lint travistest travis
......@@ -191,7 +187,7 @@ test-py34: $(PY34)
PYTHON=python3.4.8 PATH=$(BUILD_RUNTIMES)/versions/python3.4.8/bin:$(PATH) make develop basictest
test-py35: $(PY35)
PYTHON=python3.5.5 PATH=$(BUILD_RUNTIMES)/versions/python3.5.5/bin:$(PATH) make develop basictest
PYTHON=python3.5.5 PATH=$(BUILD_RUNTIMES)/versions/python3.5.5/bin:$(PATH) GEVENTTEST_COVERAGE=1 make develop basictest coverage_combine
test-py36: $(PY36)
PYTHON=python3.6.7 PATH=$(BUILD_RUNTIMES)/versions/python3.6.7/bin:$(PATH) make develop lint basictest
......
......@@ -138,23 +138,13 @@ cache:
- '%LOCALAPPDATA%\pip\Cache'
build_script:
# Build the compiled extension. First we make an sdist, then
# we install from that, to test sdist building issues. Finally we
# build a wheel for downloading purposes
- "%CMD_IN_ENV% %PYEXE% setup.py sdist --formats=gztar"
- ps: "ls dist"
# Now install the sdist.
# I couldn't get wildcards to work for pip install, so stuff it
# into a variable, using python to glob.
- "%PYEXE% -c \"import glob; print(glob.glob('dist/*gz')[0])\" > whl.txt"
- set /p PYWHL=<whl.txt
- "%PYEXE% -m pip install -U --upgrade-strategy=eager %PYWHL%[test,events,dnspython]"
- "%PYEXE% -m pip install -U --upgrade-strategy=eager -e .[test,events,dnspython]"
test_script:
# Run the project tests
- "%PYEXE% -c \"import gevent.core; print(gevent.core.loop)\""
- "%PYEXE% -c \"import gevent; print(gevent.config.settings['resolver'].get_options())\""
- "cd src/greentest && %PYEXE% testrunner.py --config known_failures.py --quiet && cd ../.."
- "%PYEXE% -mgevent.tests --config known_failures.py --quiet"
after_test:
- "%CMD_IN_ENV% %PYEXE% setup.py bdist_wheel"
......
......@@ -177,8 +177,7 @@ tests on one version of Python during development, begin with the
above instructions to install gevent in a virtual environment and then
run::
(env) $ cd src/greentest
(env) $ python ./testrunner.py
(env) $ python -mgevent.tests
Before submitting a pull request, it's a good idea to run the tests
across all supported versions of Python, and to check the code quality
......@@ -192,8 +191,7 @@ The testrunner accepts a ``--coverage`` argument to enable code
coverage metrics through the `coverage.py`_ package. That would go
something like this::
cd src/greentest
python testrunner.py --coverage
python -m gevent.tests --coverage
coverage combine
coverage html -i
<open htmlcov/index.html>
......
......@@ -373,7 +373,7 @@ def run_setup(ext_modules, run_make):
# We don't run coverage on Windows, and pypy can't build it there
# anyway (coveralls -> cryptopgraphy -> openssl)
'coverage>=4.0 ; sys_platform != "win32"',
'coverage>=5.0a3 ; sys_platform != "win32"',
'coveralls>=1.0 ; sys_platform != "win32"',
'futures ; python_version == "2.7"',
......
# -*- 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
......
......@@ -3,7 +3,14 @@
.. deprecated:: 1.3
Use :mod:`gevent.resolver.ares`
"""
import warnings
warnings.warn(
"gevent.resolver_ares is deprecated and will be removed in 1.5. "
"Use gevent.resolver.ares instead.",
DeprecationWarning,
stacklevel=2
)
del warnings
from gevent.resolver.ares import * # pylint:disable=wildcard-import,unused-wildcard-import
import gevent.resolver.ares as _ares
__all__ = _ares.__all__
......
"""Backwards compatibility alias for :mod:`gevent.resolver.thread`.
.. deprecated:: 1.3
Use :mod:`gevent.resolver.cares`
Use :mod:`gevent.resolver.thread`
"""
import warnings
warnings.warn(
"gevent.resolver_thread is deprecated and will be removed in 1.5. "
"Use gevent.resolver.thread instead.",
DeprecationWarning,
stacklevel=2
)
del warnings
from gevent.resolver.thread import * # pylint:disable=wildcard-import,unused-wildcard-import
import gevent.resolver.thread as _thread
__all__ = _thread.__all__
......
......@@ -20,106 +20,107 @@
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
# THE SOFTWARE.
# package is named greentest, not test, so it won't be confused with test in stdlib
import unittest
# pylint:disable=unused-import
from greentest.sysinfo import VERBOSE
from greentest.sysinfo import WIN
from greentest.sysinfo import LINUX
from greentest.sysinfo import LIBUV
from greentest.sysinfo import CFFI_BACKEND
from greentest.sysinfo import DEBUG
from greentest.sysinfo import RUN_LEAKCHECKS
from greentest.sysinfo import RUN_COVERAGE
from .sysinfo import VERBOSE
from .sysinfo import WIN
from .sysinfo import LINUX
from .sysinfo import LIBUV
from .sysinfo import CFFI_BACKEND
from .sysinfo import DEBUG
from .sysinfo import RUN_LEAKCHECKS
from .sysinfo import RUN_COVERAGE
from greentest.sysinfo import PY2
from greentest.sysinfo import PY3
from greentest.sysinfo import PY34
from greentest.sysinfo import PY36
from greentest.sysinfo import PY37
from .sysinfo import PY2
from .sysinfo import PY3
from .sysinfo import PY34
from .sysinfo import PY36
from .sysinfo import PY37
from greentest.sysinfo import PYPY
from greentest.sysinfo import PYPY3
from greentest.sysinfo import CPYTHON
from .sysinfo import PYPY
from .sysinfo import PYPY3
from .sysinfo import CPYTHON
from greentest.sysinfo import PLATFORM_SPECIFIC_SUFFIXES
from greentest.sysinfo import NON_APPLICABLE_SUFFIXES
from greentest.sysinfo import SHARED_OBJECT_EXTENSION
from .sysinfo import PLATFORM_SPECIFIC_SUFFIXES
from .sysinfo import NON_APPLICABLE_SUFFIXES
from .sysinfo import SHARED_OBJECT_EXTENSION
from greentest.sysinfo import RUNNING_ON_TRAVIS
from greentest.sysinfo import RUNNING_ON_APPVEYOR
from greentest.sysinfo import RUNNING_ON_CI
from .sysinfo import RUNNING_ON_TRAVIS
from .sysinfo import RUNNING_ON_APPVEYOR
from .sysinfo import RUNNING_ON_CI
from greentest.sysinfo import RESOLVER_NOT_SYSTEM
from greentest.sysinfo import RESOLVER_DNSPYTHON
from greentest.sysinfo import RESOLVER_ARES
from .sysinfo import RESOLVER_NOT_SYSTEM
from .sysinfo import RESOLVER_DNSPYTHON
from .sysinfo import RESOLVER_ARES
from greentest.sysinfo import EXPECT_POOR_TIMER_RESOLUTION
from .sysinfo import EXPECT_POOR_TIMER_RESOLUTION
from greentest.sysinfo import CONN_ABORTED_ERRORS
from .sysinfo import CONN_ABORTED_ERRORS
from greentest.skipping import skipOnWindows
from greentest.skipping import skipOnAppVeyor
from greentest.skipping import skipOnCI
from greentest.skipping import skipOnPyPy3OnCI
from greentest.skipping import skipOnPyPy
from greentest.skipping import skipOnPyPyOnCI
from greentest.skipping import skipOnPyPy3
from greentest.skipping import skipIf
from greentest.skipping import skipOnLibev
from greentest.skipping import skipOnLibuv
from greentest.skipping import skipOnLibuvOnWin
from greentest.skipping import skipOnLibuvOnCI
from greentest.skipping import skipOnLibuvOnCIOnPyPy
from greentest.skipping import skipOnLibuvOnPyPyOnWin
from greentest.skipping import skipOnPurePython
from greentest.skipping import skipWithCExtensions
from greentest.skipping import skipOnLibuvOnTravisOnCPython27
from greentest.skipping import skipOnPy37
from .skipping import skipOnWindows
from .skipping import skipOnAppVeyor
from .skipping import skipOnCI
from .skipping import skipOnPyPy3OnCI
from .skipping import skipOnPyPy
from .skipping import skipOnPyPyOnCI
from .skipping import skipOnPyPy3
from .skipping import skipIf
from .skipping import skipOnLibev
from .skipping import skipOnLibuv
from .skipping import skipOnLibuvOnWin
from .skipping import skipOnLibuvOnCI
from .skipping import skipOnLibuvOnCIOnPyPy
from .skipping import skipOnLibuvOnPyPyOnWin
from .skipping import skipOnPurePython
from .skipping import skipWithCExtensions
from .skipping import skipOnLibuvOnTravisOnCPython27
from .skipping import skipOnPy37
from greentest.exception import ExpectedException
from .exception import ExpectedException
from greentest.leakcheck import ignores_leakcheck
from .leakcheck import ignores_leakcheck
from greentest.params import LARGE_TIMEOUT
from .params import LARGE_TIMEOUT
from greentest.params import DEFAULT_LOCAL_HOST_ADDR
from greentest.params import DEFAULT_LOCAL_HOST_ADDR6
from greentest.params import DEFAULT_BIND_ADDR
from .params import DEFAULT_LOCAL_HOST_ADDR
from .params import DEFAULT_LOCAL_HOST_ADDR6
from .params import DEFAULT_BIND_ADDR
from greentest.params import DEFAULT_SOCKET_TIMEOUT
from greentest.params import DEFAULT_XPC_SOCKET_TIMEOUT
from .params import DEFAULT_SOCKET_TIMEOUT
from .params import DEFAULT_XPC_SOCKET_TIMEOUT
main = unittest.main
from greentest.hub import QuietHub
from .hub import QuietHub
import gevent.hub
gevent.hub.set_default_hub_class(QuietHub)
from greentest.sockets import bind_and_listen
from greentest.sockets import tcp_listener
from .sockets import bind_and_listen
from .sockets import tcp_listener
from greentest.openfiles import get_number_open_files
from greentest.openfiles import get_open_files
from .openfiles import get_number_open_files
from .openfiles import get_open_files
from greentest.testcase import TestCase
from .testcase import TestCase
from greentest.modules import walk_modules
from .modules import walk_modules
BaseTestCase = unittest.TestCase
from greentest.flaky import reraiseFlakyTestTimeout
from greentest.flaky import reraiseFlakyTestRaceCondition
from .flaky import reraiseFlakyTestTimeout
from .flaky import reraiseFlakyTestRaceCondition
from .flaky import reraises_flaky_timeout
from .flaky import reraises_flaky_race_condition
try:
from unittest import mock
......
......@@ -25,8 +25,8 @@ import unittest
from gevent.util import dump_stacks
from greentest import sysinfo
from greentest import six
from . import sysinfo
from . import six
class FlakyAssertionError(AssertionError):
"Re-raised so that we know it's a known-flaky test."
......@@ -96,7 +96,7 @@ if sysinfo.RUNNING_ON_CI or (sysinfo.PYPY and sysinfo.WIN):
reraiseFlakyTestTimeoutLibuv = reraiseFlakyTestTimeout
def reraises_flaky_timeout(exc_kind):
def reraises_flaky_timeout(exc_kind=AssertionError, _func=reraiseFlakyTestTimeout):
def wrapper(f):
@functools.wraps(f)
......@@ -104,7 +104,10 @@ def reraises_flaky_timeout(exc_kind):
try:
f(*args)
except exc_kind:
reraiseFlakyTestTimeout()
_func()
return m
return wrapper
def reraises_flaky_race_condition(exc_kind=AssertionError):
return reraises_flaky_timeout(exc_kind, _func=reraiseFlakyTestRaceCondition)
......@@ -22,7 +22,7 @@ from __future__ import absolute_import, print_function, division
from gevent.hub import Hub
from greentest.exception import ExpectedException
from .exception import ExpectedException
class QuietHub(Hub):
......
......@@ -68,7 +68,11 @@ class _RefCountChecker(object):
self.needs_setUp = False
def _ignore_object_p(self, obj):
if obj is self or obj in self.__dict__.values() or obj == self._ignore_object_p:
if (
obj is self
or obj in self.__dict__.values()
or obj == self._ignore_object_p # pylint:disable=comparison-with-callable
):
return False
kind = type(obj)
if kind in self.IGNORED_TYPES:
......
......@@ -19,14 +19,21 @@
# THE SOFTWARE.
from __future__ import absolute_import, print_function, division
import importlib
import os.path
import warnings
import gevent
from greentest import sysinfo
from greentest import six
from . import sysinfo
OPTIONAL_MODULES = ['resolver_ares']
OPTIONAL_MODULES = [
'gevent.resolver_ares',
'gevent.resolver.ares',
'gevent.libev',
'gevent.libev.watcher',
]
def walk_modules(basedir=None, modpath=None, include_so=False, recursive=False):
......@@ -45,6 +52,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
......@@ -58,12 +67,15 @@ def walk_modules(basedir=None, modpath=None, include_so=False, recursive=False):
if x in ['__init__', 'core', 'ares', '_util', '_semaphore',
'corecffi', '_corecffi', '_corecffi_build']:
continue
if x in OPTIONAL_MODULES:
modname = modpath + x
if modname in OPTIONAL_MODULES:
try:
six.exec_("import %s" % x, {})
with warnings.catch_warnings():
warnings.simplefilter('ignore', DeprecationWarning)
importlib.import_module(modname)
except ImportError:
continue
yield path, modpath + x
yield path, modname
elif include_so and fn.endswith(sysinfo.SHARED_OBJECT_EXTENSION):
if '.pypy-' in fn:
continue
......
......@@ -18,9 +18,9 @@ print('Running with patch_all(%s): %s' % (','.join('%s=%r' % x for x in kwargs.i
from gevent import monkey
monkey.patch_all(**kwargs)
from greentest.sysinfo import RUNNING_ON_APPVEYOR
from greentest.sysinfo import PY37
from greentest.patched_tests_setup import disable_tests_in_source
from .sysinfo import RUNNING_ON_APPVEYOR
from .sysinfo import PY37
from .patched_tests_setup import disable_tests_in_source
try:
from test import support
except ImportError:
......
......@@ -23,7 +23,7 @@ import os
import unittest
import re
from greentest import sysinfo
from . import sysinfo
# Linux/OS X/BSD platforms can implement this by calling out to lsof
......@@ -75,11 +75,11 @@ def default_get_number_open_files():
# Linux only
fd_directory = '/proc/%d/fd' % os.getpid()
return len(os.listdir(fd_directory))
else:
try:
return len(get_open_files(pipes=True)) - 1
except (OSError, AssertionError, unittest.SkipTest):
return 0
try:
return len(get_open_files(pipes=True)) - 1
except (OSError, AssertionError, unittest.SkipTest):
return 0
lsof_get_open_files = default_get_open_files
......
......@@ -19,26 +19,26 @@
# THE SOFTWARE.
from greentest.sysinfo import PY3
from greentest.sysinfo import PYPY
from greentest.sysinfo import WIN
from greentest.sysinfo import LIBUV
from greentest.sysinfo import OSX
from .sysinfo import PY3
from .sysinfo import PYPY
from .sysinfo import WIN
from .sysinfo import LIBUV
from .sysinfo import OSX
from greentest.sysinfo import RUNNING_ON_TRAVIS
from greentest.sysinfo import RUNNING_ON_APPVEYOR
from greentest.sysinfo import EXPECT_POOR_TIMER_RESOLUTION
from greentest.sysinfo import RESOLVER_ARES
from .sysinfo import RUNNING_ON_TRAVIS
from .sysinfo import RUNNING_ON_APPVEYOR
from .sysinfo import EXPECT_POOR_TIMER_RESOLUTION
from .sysinfo import RESOLVER_ARES
# Travis is slow and overloaded; Appveyor used to be faster, but
# as of Dec 2015 it's almost always slower and/or has much worse timer
# resolution
CI_TIMEOUT = 10
CI_TIMEOUT = 15
if (PY3 and PYPY) or (PYPY and WIN and LIBUV):
# pypy3 is very slow right now,
# as is PyPy2 on windows (which only has libuv)
CI_TIMEOUT = 15
CI_TIMEOUT = 20
if PYPY and LIBUV:
# slow and flaky timeouts
LOCAL_TIMEOUT = CI_TIMEOUT
......
# pylint:disable=missing-docstring,invalid-name
# pylint:disable=missing-docstring,invalid-name,too-many-lines
from __future__ import print_function, absolute_import, division
import collections
......@@ -13,26 +13,28 @@ import os
# import platform
import re
from greentest.sysinfo import RUNNING_ON_APPVEYOR as APPVEYOR
from greentest.sysinfo import RUNNING_ON_TRAVIS as TRAVIS
from greentest.sysinfo import RESOLVER_NOT_SYSTEM as ARES
from greentest.sysinfo import RUN_COVERAGE
from .sysinfo import RUNNING_ON_APPVEYOR as APPVEYOR
from .sysinfo import RUNNING_ON_TRAVIS as TRAVIS
from .sysinfo import RESOLVER_NOT_SYSTEM as ARES
from .sysinfo import RUN_COVERAGE
from greentest.sysinfo import PYPY
from greentest.sysinfo import PYPY3
from greentest.sysinfo import PY3
from greentest.sysinfo import PY2
from greentest.sysinfo import PY34
from greentest.sysinfo import PY35
from greentest.sysinfo import PY36
from greentest.sysinfo import PY37
from .sysinfo import PYPY
from .sysinfo import PYPY3
from .sysinfo import PY3
from .sysinfo import PY2
from .sysinfo import PY34
from .sysinfo import PY35
from .sysinfo import PY36
from .sysinfo import PY37
from greentest.sysinfo import WIN
from greentest.sysinfo import OSX
from .sysinfo import WIN
from .sysinfo import OSX
from greentest.sysinfo import LIBUV
from greentest.sysinfo import CFFI_BACKEND
from .sysinfo import LIBUV
from .sysinfo import CFFI_BACKEND
from . import flaky
CPYTHON = not PYPY
......@@ -536,6 +538,14 @@ def _gc_at_end():
gc.collect()
gc.collect()
@contextlib.contextmanager
def _flaky_socket_timeout():
import socket
try:
yield
except socket.timeout:
flaky.reraiseFlakyTestTimeout()
# Map from FQN to a context manager that will be wrapped around
# that test.
wrapped_tests = {
......@@ -577,6 +587,13 @@ if WIN:
'test_ssl.ThreadedTests.test_socketserver',
]
# These are a problem on 3.5; on 3.6+ they wind up getting (accidentally) disabled.
wrapped_tests.update({
'test_socket.SendfileUsingSendTest.testWithTimeout': _flaky_socket_timeout,
'test_socket.SendfileUsingSendTest.testOffset': _flaky_socket_timeout,
'test_socket.SendfileUsingSendTest.testRegularFile': _flaky_socket_timeout,
})
if PYPY:
disabled_tests += [
# Does not exist in the CPython test suite, tests for a specific bug
......@@ -690,12 +707,7 @@ if PYPY3:
]
if PYPY and sys.pypy_version_info[:4] in ( # pylint:disable=no-member
(5, 8, 0, 'beta'), (5, 9, 0, 'beta'), (5, 10, 1, 'final')):
# 3.5 is beta. Hard to say what are real bugs in us vs real bugs in pypy.
# For that reason, we pin these patches exactly to the version in use.
if PYPY and PY3:
disabled_tests += [
# This fails to close all the FDs, at least on CI. On OS X, many of the
# POSIXProcessTestCase fd tests have issues.
......@@ -1074,7 +1086,7 @@ def disable_tests_in_source(source, filename):
# If we do it on a def-by-def basis, we can break syntax
# if the function is already decorated
pattern = r'^import .*'
replacement = r'from greentest import patched_tests_setup as _GEVENT_PTS;'
replacement = r'from gevent.testing import patched_tests_setup as _GEVENT_PTS;'
replacement += r'import unittest as _GEVENT_UTS;'
replacement += r'\g<0>'
source, n = re.subn(pattern, replacement, source, 1, re.MULTILINE)
......@@ -1085,9 +1097,10 @@ def disable_tests_in_source(source, filename):
# so use [ \t]+. Without indentation, test_main, commonly used as the
# __main__ function at the top level, could get matched. \s matches
# newlines even in MULTILINE mode so it would still match that.
my_disabled_testcases = set()
for test in my_disabled_tests:
testcase = test.split('.')[-1]
my_disabled_testcases.add(testcase)
# def foo_bar(self)
# ->
# @_GEVENT_UTS.skip('Removed by patched_tests_setup')
......@@ -1101,6 +1114,10 @@ def disable_tests_in_source(source, filename):
for test in my_wrapped_tests:
testcase = test.split('.')[-1]
if testcase in my_disabled_testcases:
print("Not wrapping %s because it is skipped" % (test,))
continue
# def foo_bar(self)
# ->
# @_GEVENT_PTS._PatchedTest('file.Case.name')
......
......@@ -21,7 +21,7 @@ from __future__ import absolute_import, print_function, division
import unittest
from greentest import sysinfo
from . import sysinfo
def _identity(f):
return f
......
......@@ -19,7 +19,7 @@
# THE SOFTWARE.
from __future__ import absolute_import, print_function, division
from greentest.params import DEFAULT_BIND_ADDR_TUPLE
from .params import DEFAULT_BIND_ADDR_TUPLE
def bind_and_listen(sock, address=DEFAULT_BIND_ADDR_TUPLE, backlog=50, reuse_addr=True):
from socket import SOL_SOCKET, SO_REUSEADDR, error
......
......@@ -23,9 +23,9 @@ from functools import wraps
from gevent.hub import _get_hub
from greentest.hub import QuietHub
from .hub import QuietHub
from greentest.patched_tests_setup import get_switch_expected
from .patched_tests_setup import get_switch_expected
def wrap_switch_count_check(method):
@wraps(method)
......
......@@ -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
......@@ -60,10 +60,10 @@ PY35 = None
PY36 = None
PY37 = None
NON_APPLICABLE_SUFFIXES = []
NON_APPLICABLE_SUFFIXES = ()
if sys.version_info[0] == 3:
# Python 3
NON_APPLICABLE_SUFFIXES.extend(('2', '279'))
NON_APPLICABLE_SUFFIXES += ('2', '279')
PY2 = False
PY3 = True
if sys.version_info[1] >= 4:
......@@ -79,11 +79,11 @@ elif sys.version_info[0] == 2:
# Any python 2
PY3 = False
PY2 = True
NON_APPLICABLE_SUFFIXES.append('3')
NON_APPLICABLE_SUFFIXES += ('3',)
if (sys.version_info[1] < 7
or (sys.version_info[1] == 7 and sys.version_info[2] < 9)):
# Python 2, < 2.7.9
NON_APPLICABLE_SUFFIXES.append('279')
NON_APPLICABLE_SUFFIXES += ('279',)
PYPY3 = PYPY and PY3
......@@ -96,9 +96,9 @@ PYGTE279 = (
)
if WIN:
NON_APPLICABLE_SUFFIXES.append("posix")
NON_APPLICABLE_SUFFIXES += ("posix",)
# This is intimately tied to FileObjectPosix
NON_APPLICABLE_SUFFIXES.append("fileobject2")
NON_APPLICABLE_SUFFIXES += ("fileobject2",)
SHARED_OBJECT_EXTENSION = ".pyd"
else:
SHARED_OBJECT_EXTENSION = ".so"
......@@ -111,7 +111,7 @@ RUNNING_ON_CI = RUNNING_ON_TRAVIS or RUNNING_ON_APPVEYOR
if RUNNING_ON_APPVEYOR:
# We can't exec corecext on appveyor if we haven't run setup.py in
# 'develop' mode (i.e., we install)
NON_APPLICABLE_SUFFIXES.append('corecext')
NON_APPLICABLE_SUFFIXES += ('corecext',)
EXPECT_POOR_TIMER_RESOLUTION = (PYPY3
or RUNNING_ON_APPVEYOR
......
......@@ -20,21 +20,24 @@
from __future__ import absolute_import, print_function, division
import sys
from time import time
import os.path
from contextlib import contextmanager
from unittest import TestCase as BaseTestCase
from functools import wraps
import gevent
from greentest import sysinfo
from greentest import params
from greentest import leakcheck
from greentest import errorhandler
from greentest import flaky
from . import sysinfo
from . import params
from . import leakcheck
from . import errorhandler
from . import flaky
from greentest.patched_tests_setup import get_switch_expected
from .patched_tests_setup import get_switch_expected
class TimeAssertMixin(object):
@flaky.reraises_flaky_timeout()
def assertTimeoutAlmostEqual(self, first, second, places=None, msg=None, delta=None):
try:
self.assertAlmostEqual(first, second, places=places, msg=msg, delta=delta)
......@@ -51,6 +54,28 @@ class TimeAssertMixin(object):
self.assertLessEqual(time_taken, max_time)
self.assertGreaterEqual(time_taken, min_time)
@contextmanager
def runs_in_given_time(self, expected, fuzzy=None):
if fuzzy is None:
if sysinfo.EXPECT_POOR_TIMER_RESOLUTION or sysinfo.LIBUV:
# The noted timer jitter issues on appveyor/pypy3
fuzzy = expected * 5.0
else:
fuzzy = expected / 2.0
start = time()
yield
elapsed = time() - start
try:
self.assertTrue(
expected - fuzzy <= elapsed <= expected + fuzzy,
'Expected: %r; elapsed: %r; fuzzy %r' % (expected, elapsed, fuzzy))
except AssertionError:
flaky.reraiseFlakyTestRaceCondition()
def runs_in_no_time(
self,
fuzzy=(0.01 if not sysinfo.EXPECT_POOR_TIMER_RESOLUTION and not sysinfo.LIBUV else 1.0)):
return self.runs_in_given_time(0.0, fuzzy)
def _wrap_timeout(timeout, method):
......
......@@ -22,9 +22,9 @@ import time
import gevent
from greentest import sysinfo
from greentest import leakcheck
from greentest.testcase import TestCase
from . import sysinfo
from . import leakcheck
from .testcase import TestCase
SMALLEST_RELIABLE_DELAY = 0.001 # 1ms, because of libuv
......
import sys
import os
from greentest import six
from . import six
import traceback
import unittest
import threading
......@@ -298,8 +298,18 @@ def run(command, **kwargs):
return RunResult(result, out, name)
def find_setup_py_above(a_file):
"Return the directory containing setup.py somewhere above *a_file*"
root = os.path.dirname(os.path.abspath(a_file))
while not os.path.exists(os.path.join(root, 'setup.py')):
prev, root = root, os.path.dirname(root)
if root == prev:
# Let's avoid infinite loops at root
raise AssertionError('could not find my setup.py')
return root
class TestServer(unittest.TestCase):
cwd = '../../examples/'
args = []
before_delay = 3
after_delay = 0.5
......@@ -307,6 +317,19 @@ class TestServer(unittest.TestCase):
server = None # subclasses define this to be the path to the server.py
start_kwargs = None
def find_setup_py(self):
"Return the directory containing setup.py"
return find_setup_py_above(__file__)
# XXX: We need to extend this if we want it to be useful
# for other packages; our __file__ won't work for them.
# We can look at the CWD, and we can look at the __file__ of the
# sys.modules[type(self).__module__].
@property
def cwd(self):
root = self.find_setup_py()
return os.path.join(root, 'examples')
def start(self):
kwargs = self.start_kwargs or {}
return start([sys.executable, '-u', self.server] + self.args, cwd=self.cwd, **kwargs)
......
-----BEGIN PRIVATE KEY-----
MIICdwIBADANBgkqhkiG9w0BAQEFAASCAmEwggJdAgEAAoGBANtb0+YrKuxevGpm
LrjaUhZSgz6zFAmuGFmKmUbdjmfv9zSmmdsQIksK++jK0Be9LeZy20j6ahOfuVa0
ufEmPoP7Fy4hXegKZR9cCWcIe/A6H2xWF1IIJLRTLaU8ol/I7T+um5HD5AwAwNPP
USNU0Eegmvp+xxWu3NX2m1Veot85AgMBAAECgYA3ZdZ673X0oexFlq7AAmrutkHt
CL7LvwrpOiaBjhyTxTeSNWzvtQBkIU8DOI0bIazA4UreAFffwtvEuPmonDb3F+Iq
SMAu42XcGyVZEl+gHlTPU9XRX7nTOXVt+MlRRRxL6t9GkGfUAXI3XxJDXW3c0vBK
UL9xqD8cORXOfE06rQJBAP8mEX1ERkR64Ptsoe4281vjTlNfIbs7NMPkUnrn9N/Y
BLhjNIfQ3HFZG8BTMLfX7kCS9D593DW5tV4Z9BP/c6cCQQDcFzCcVArNh2JSywOQ
ZfTfRbJg/Z5Lt9Fkngv1meeGNPgIMLN8Sg679pAOOWmzdMO3V706rNPzSVMME7E5
oPIfAkEA8pDddarP5tCvTTgUpmTFbakm0KoTZm2+FzHcnA4jRh+XNTjTOv98Y6Ik
eO5d1ZnKXseWvkZncQgxfdnMqqpj5wJAcNq/RVne1DbYlwWchT2Si65MYmmJ8t+F
0mcsULqjOnEMwf5e+ptq5LzwbyrHZYq5FNk7ocufPv/ZQrcSSC+cFwJBAKvOJByS
x56qyGeZLOQlWS2JS3KJo59XuLFGqcbgN9Om9xFa41Yb4N9NvplFivsvZdw3m1Q/
SPIXQuT8RMPDVNQ=
-----END PRIVATE KEY-----
-----BEGIN CERTIFICATE-----
MIICVDCCAb2gAwIBAgIJANfHOBkZr8JOMA0GCSqGSIb3DQEBBQUAMF8xCzAJBgNV
BAYTAlhZMRcwFQYDVQQHEw5DYXN0bGUgQW50aHJheDEjMCEGA1UEChMaUHl0aG9u
IFNvZnR3YXJlIEZvdW5kYXRpb24xEjAQBgNVBAMTCWxvY2FsaG9zdDAeFw0xMDEw
MDgyMzAxNTZaFw0yMDEwMDUyMzAxNTZaMF8xCzAJBgNVBAYTAlhZMRcwFQYDVQQH
Ew5DYXN0bGUgQW50aHJheDEjMCEGA1UEChMaUHl0aG9uIFNvZnR3YXJlIEZvdW5k
YXRpb24xEjAQBgNVBAMTCWxvY2FsaG9zdDCBnzANBgkqhkiG9w0BAQEFAAOBjQAw
gYkCgYEA21vT5isq7F68amYuuNpSFlKDPrMUCa4YWYqZRt2OZ+/3NKaZ2xAiSwr7
6MrQF70t5nLbSPpqE5+5VrS58SY+g/sXLiFd6AplH1wJZwh78DofbFYXUggktFMt
pTyiX8jtP66bkcPkDADA089RI1TQR6Ca+n7HFa7c1fabVV6i3zkCAwEAAaMYMBYw
FAYDVR0RBA0wC4IJbG9jYWxob3N0MA0GCSqGSIb3DQEBBQUAA4GBAHPctQBEQ4wd
BJ6+JcpIraopLn8BGhbjNWj40mmRqWB/NAWF6M5ne7KpGAu7tLeG4hb1zLaldK8G
lxy2GPSRF6LFS48dpEj2HbMv2nvv6xxalDMJ9+DicWgAKTQ6bcX2j3GUkCR0g/T1
CRlNBAAlvhKzO7Clpf9l0YKBEfraJByX
-----END CERTIFICATE-----
......@@ -2,5 +2,5 @@
from __future__ import print_function, absolute_import, division
if __name__ == '__main__':
from greentest import testrunner
from gevent.testing import testrunner
testrunner.main()
......@@ -6,17 +6,17 @@ import os
import sys
import struct
from greentest.sysinfo import RUNNING_ON_APPVEYOR as APPVEYOR
from greentest.sysinfo import RUNNING_ON_TRAVIS as TRAVIS
from greentest.sysinfo import RUN_LEAKCHECKS as LEAKTEST
from greentest.sysinfo import RUN_COVERAGE as COVERAGE
from greentest.sysinfo import RESOLVER_NOT_SYSTEM
from gevent.testing.sysinfo import RUNNING_ON_APPVEYOR as APPVEYOR
from gevent.testing.sysinfo import RUNNING_ON_TRAVIS as TRAVIS
from gevent.testing.sysinfo import RUN_LEAKCHECKS as LEAKTEST
from gevent.testing.sysinfo import RUN_COVERAGE as COVERAGE
from gevent.testing.sysinfo import RESOLVER_NOT_SYSTEM
from greentest.sysinfo import PYPY
from greentest.sysinfo import PY3
from greentest.sysinfo import PY35
from gevent.testing.sysinfo import PYPY
from gevent.testing.sysinfo import PY3
from gevent.testing.sysinfo import PY35
from greentest.sysinfo import LIBUV
from gevent.testing.sysinfo import LIBUV
IGNORED_TESTS = []
......@@ -85,6 +85,32 @@ if sys.platform == 'win32':
# too tight for appveyor. This happens even if Event isn't
# monkey-patched
'FLAKY test_threading.py',
# Starting in November 2018, on Python 3.7.0, we observe this test crashing.
# I can't reproduce locally.
# | C:\Python37-x64\python.exe -u -mgevent.tests.test__greenness
# 127.0.0.1 - - [09/Nov/2018 16:34:12] code 501, message Unsupported method ('GET')
# 127.0.0.1 - - [09/Nov/2018 16:34:12] "GET / HTTP/1.1" 501 -
# .
# ----------------------------------------------------------------------
# Ran 1 test in 0.031s
# OK
# Windows fatal exception: access violation
# Current thread 0x000003c8 (most recent call first):
# File "c:\projects\gevent\src\gevent\threadpool.py", line 261 in _worker
# Thread 0x00000600 (most recent call first):
# File "c:\projects\gevent\src\gevent\libuv\watcher.py", line 577 in send
# File "c:\projects\gevent\src\gevent\threadpool.py", line 408 in set
# File "c:\projects\gevent\src\gevent\threadpool.py", line 290 in _worker
# Thread 0x000007d4 (most recent call first):
# File "C:\Python37-x64\lib\weakref.py", line 356 in remove
# ! C:\Python37-x64\python.exe -u -mgevent.tests.test__greenness [code 3221225477] [took 1.3s]
'FLAKY test__greenness.py',
]
if not PY35:
......@@ -189,7 +215,7 @@ if PYPY:
# This test, which normally takes 4-5s, sometimes
# hangs forever after running two tests. I cannot reproduce,
# it seems highly load dependent. Observed with both libev and libuv.
'test_threading_2.py',
'test__threading_2.py',
]
if PY3 and TRAVIS:
......@@ -236,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)
"""
Various tests for synchronization primitives.
"""
# pylint:disable=no-member,abstract-method
import sys
import time
try:
......@@ -15,7 +16,7 @@ try:
except ImportError:
from test import test_support as support
from greentest.testcase import TimeAssertMixin
from gevent.testing.testcase import TimeAssertMixin
def _wait():
# A crude wait/yield function not relying on synchronization primitives.
......@@ -131,7 +132,7 @@ class BaseLockTests(BaseTestCase):
def _with(err=None):
with lock:
if err is not None:
raise err
raise err # pylint:disable=raising-bad-type
_with()
# Check the lock is unacquired
Bunch(f, 1).wait_for_finished()
......@@ -153,7 +154,7 @@ class BaseLockTests(BaseTestCase):
self.assertEqual(n, len(threading.enumerate()))
class LockTests(BaseLockTests):
class LockTests(BaseLockTests): # pylint:disable=abstract-method
"""
Tests for non-recursive, weak locks
(which can be acquired and released from different threads).
......@@ -168,7 +169,7 @@ class LockTests(BaseLockTests):
lock.acquire()
phase.append(None)
start_new_thread(f, ())
while len(phase) == 0:
while not phase:
_wait()
_wait()
self.assertEqual(len(phase), 1)
......@@ -436,9 +437,10 @@ class BaseSemaphoreTests(BaseTestCase):
raise NotImplementedError()
def test_constructor(self):
self.assertRaises(ValueError, self.semtype, value = -1)
self.assertRaises(ValueError, self.semtype, value=-1)
# Py3 doesn't have sys.maxint
self.assertRaises(ValueError, self.semtype, value = -getattr(sys, 'maxint', getattr(sys, 'maxsize', None)))
self.assertRaises(ValueError, self.semtype,
value=-getattr(sys, 'maxint', getattr(sys, 'maxsize', None)))
def test_acquire(self):
sem = self.semtype(1)
......@@ -509,7 +511,7 @@ class BaseSemaphoreTests(BaseTestCase):
# There can be a thread switch between acquiring the semaphore and
# appending the result, therefore results will not necessarily be
# ordered.
self.assertEqual(sorted(results), [False] * 7 + [True] * 3 )
self.assertEqual(sorted(results), [False] * 7 + [True] * 3)
def test_default_value(self):
# The default initial value is 1.
......@@ -534,7 +536,7 @@ class BaseSemaphoreTests(BaseTestCase):
with sem:
self.assertFalse(sem.acquire(False))
if err:
raise err
raise err # pylint:disable=raising-bad-type
_with()
self.assertTrue(sem.acquire(False))
sem.release()
......@@ -603,7 +605,7 @@ class BarrierTests(BaseTestCase):
"""
Test that a barrier is passed in lockstep
"""
results = [[],[]]
results = [[], []]
def f():
self.multipass(results, passes)
self.run_threads(f)
......@@ -657,7 +659,6 @@ class BarrierTests(BaseTestCase):
results2.append(True)
except RuntimeError:
self.barrier.abort()
pass
self.run_threads(f)
self.assertEqual(len(results1), 0)
......@@ -713,7 +714,7 @@ class BarrierTests(BaseTestCase):
results2.append(True)
except RuntimeError:
self.barrier.abort()
pass
# Synchronize and reset the barrier. Must synchronize first so
# that everyone has left it when we reset, and after so that no
# one enters it before the reset.
......
......@@ -9,10 +9,10 @@ from unittest import SkipTest
import socket
import ssl
import greentest
from greentest import DEFAULT_XPC_SOCKET_TIMEOUT
from greentest import util
from greentest import params
import gevent.testing as greentest
from gevent.testing import DEFAULT_XPC_SOCKET_TIMEOUT
from gevent.testing import util
from gevent.testing import params
@greentest.skipOnCI("Timing issues sometimes lead to a connection refused")
class Test_wsgiserver(util.TestServer):
......
......@@ -8,7 +8,7 @@ from __future__ import print_function
import gc
import greentest
import gevent.testing as greentest
from gevent._ident import IdentRegistry
from gevent._compat import PYPY
......
......@@ -11,7 +11,7 @@ from gevent.monkey import get_original
from gevent._compat import thread_mod_name
from gevent._compat import NativeStrIO
from greentest.skipping import skipOnPyPyOnWindows
from gevent.testing.skipping import skipOnPyPyOnWindows
from gevent import _monitor as monitor
from gevent import config as GEVENT_CONFIG
......
......@@ -5,7 +5,11 @@ import glob
import atexit
# subprocess: include in subprocess tests
from greentest import util
from gevent.testing import util
# XXX: Generalize this so other packages can use it.
setup_py = util.find_setup_py_above(__file__)
greentest = os.path.join(setup_py, 'src', 'greentest')
TIMEOUT = 120
directory = '%s.%s' % sys.version_info[:2]
......@@ -13,6 +17,10 @@ full_directory = '%s.%s.%s' % sys.version_info[:3]
if hasattr(sys, 'pypy_version_info'):
directory += 'pypy'
full_directory += 'pypy'
directory = os.path.join(greentest, directory)
full_directory = os.path.join(greentest, full_directory)
version = '%s.%s.%s' % sys.version_info[:3]
if sys.version_info[3] == 'alpha':
version += 'a%s' % sys.version_info[4]
......@@ -62,7 +70,7 @@ def TESTRUNNER(tests=None):
if tests and not sys.platform.startswith("win"):
atexit.register(os.system, 'rm -f */@test*')
basic_args = [sys.executable, '-u', '-W', 'ignore', '-m' 'greentest.monkey_test']
basic_args = [sys.executable, '-u', '-W', 'ignore', '-m' 'gevent.testing.monkey_test']
for filename in tests:
if filename in version_tests:
util.log("Overriding %s from %s with file from %s", filename, directory, full_directory)
......@@ -75,7 +83,7 @@ def TESTRUNNER(tests=None):
def main():
from greentest import testrunner
from gevent.testing import testrunner
return testrunner.run_many(list(TESTRUNNER(sys.argv[1:])))
......
"""Check __all__, __implements__, __extensions__, __imports__ of the modules"""
from __future__ import print_function
from greentest import six
import sys
import unittest
import types
from greentest.modules import walk_modules
from greentest.sysinfo import PLATFORM_SPECIFIC_SUFFIXES
import importlib
import warnings
from gevent.testing import six
from gevent.testing.modules import walk_modules
from gevent.testing.sysinfo import PLATFORM_SPECIFIC_SUFFIXES
from gevent._patcher import MAPPING
......@@ -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',
......@@ -133,7 +140,7 @@ class Test(unittest.TestCase):
if hasattr(self.stdlib_module, name):
raise AssertionError("'%r' is not an extension, it is found in %r" % (name, self.stdlib_module))
def check_completeness(self):
def check_completeness(self): # pylint:disable=too-many-branches
"""Check that __all__ (or dir()) of the corresponsing stdlib is a subset of __all__ of this module"""
missed = []
for name in self.stdlib_all:
......@@ -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
......
......@@ -19,7 +19,7 @@
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
# THE SOFTWARE.
import greentest
import gevent.testing as greentest
import gevent
from gevent import util, socket
......@@ -36,10 +36,10 @@ class Test(greentest.TestCase):
try:
state.append('start')
gevent.sleep(DELAY * 3.0)
except:
except: # pylint:disable=bare-except
state.append('except')
# catching GreenletExit
pass
state.append('finished')
g = gevent.spawn(test)
......@@ -68,7 +68,9 @@ class Test(greentest.TestCase):
def _test_wait_read_invalid_switch(self, sleep):
sock1, sock2 = socket.socketpair()
try:
p = gevent.spawn(util.wrap_errors(AssertionError, socket.wait_read), sock1.fileno())
p = gevent.spawn(util.wrap_errors(AssertionError,
socket.wait_read), # pylint:disable=no-member
sock1.fileno())
gevent.get_hub().loop.run_callback(switch_None, p)
if sleep is not None:
gevent.sleep(sleep)
......
......@@ -20,7 +20,7 @@
# THE SOFTWARE.
import sys
import greentest
import gevent.testing as greentest
import weakref
import time
import gc
......@@ -30,7 +30,8 @@ from gevent import Timeout
from gevent import get_hub
from greentest.timing import SMALL_TICK as DELAY
from gevent.testing.timing import SMALL_TICK as DELAY
from gevent.testing import flaky
class Error(Exception):
......@@ -106,6 +107,8 @@ class Test(greentest.TestCase):
@greentest.skipOnAppVeyor("Timing is flaky, especially under Py 3.4/64-bit")
@greentest.skipOnPyPy3OnCI("Timing is flaky, especially under Py 3.4/64-bit")
@greentest.reraises_flaky_timeout(Timeout)
def test_api(self):
# Nothing happens if with-block finishes before the timeout expires
t = Timeout(DELAY * 2)
......@@ -173,7 +176,7 @@ class Test(greentest.TestCase):
gc.collect()
self.assertFalse(err_ref(), err_ref)
@flaky.reraises_flaky_race_condition()
def test_nested_timeout(self):
with Timeout(DELAY, False):
with Timeout(DELAY * 10, False):
......
......@@ -2,7 +2,7 @@ from __future__ import print_function
import pickle
import sys
import greentest
import gevent.testing as greentest
try:
from gevent.resolver.cares import ares_host_result
except ImportError as ex:
......
from __future__ import print_function
import errno
import unittest
import gevent
try:
from gevent.resolver.ares import Resolver
except ImportError as ex:
Resolver = None
from gevent import socket
import gevent.testing as greentest
@unittest.skipIf(
Resolver is None,
"Needs ares resolver"
)
class TestTimeout(greentest.TestCase):
__timeout__ = 30
address = ('', 7153)
def test(self):
listener = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
try:
listener.bind(self.address)
except socket.error as ex:
if ex.errno in (errno.EPERM, errno.EADDRNOTAVAIL) or 'permission denied' in str(ex).lower():
raise unittest.SkipTest(
'This test binds on port a port that was already in use or not allowed.\n'
)
raise
def reader():
while True:
listener.recvfrom(10000)
gevent.spawn(reader)
r = Resolver(servers=['127.0.0.1'], timeout=0.001, tries=1,
udp_port=self.address[-1])
with self.assertRaisesRegex(socket.gaierror, "ARES_ETIMEOUT"):
r.gethostbyname('www.google.com')
if __name__ == '__main__':
greentest.main()
from __future__ import print_function
import greentest
import gevent.testing as greentest
import gevent
from gevent import socket
from gevent import backdoor
......
from __future__ import print_function
import os
import unittest
import gevent
from gevent import core
@unittest.skipUnless(
getattr(core, 'LIBEV_EMBED', False),
"Needs embedded libev. "
"hub.loop.fileno is only defined when "
"we embed libev for some reason. "
"Choosing specific backends is also only supported by libev "
"(not libuv), and besides, libuv has a nasty tendency to "
"abort() the process if its FD gets closed. "
)
class Test(unittest.TestCase):
# NOTE that we extend unittest.TestCase, not greentest.TestCase
# Extending the later causes the wrong hub to get used.
assertRaisesRegex = getattr(unittest.TestCase, 'assertRaisesRegex',
getattr(unittest.TestCase, 'assertRaisesRegexp'))
def _check_backend(self, backend):
hub = gevent.get_hub(backend, default=False)
try:
self.assertEqual(hub.loop.backend, backend)
gevent.sleep(0.001)
fileno = hub.loop.fileno()
if fileno is None:
raise unittest.SkipTest("backend %s lacks fileno" % (backend,))
os.close(fileno)
with self.assertRaisesRegex(SystemError, "(libev)"):
gevent.sleep(0.001)
hub.destroy()
self.assertIn('destroyed', repr(hub))
finally:
if hub.loop is not None:
hub.destroy()
def _make_test(count, backend): # pylint:disable=no-self-argument
def test(self):
self._check_backend(backend)
test.__name__ = 'test_' + backend + '_' + str(count)
return test.__name__, test
count = backend = None
for count in range(2):
for backend in core.supported_backends():
name, func = _make_test(count, backend)
locals()[name] = func
name = func = None
del count
del backend
del _make_test
if __name__ == '__main__':
unittest.main()
......@@ -2,7 +2,7 @@
from __future__ import absolute_import, print_function, division
import sys
import unittest
import greentest
import gevent.testing as greentest
from gevent import core
......
from __future__ import print_function
import gevent.monkey; gevent.monkey.patch_all()
import gevent.monkey
gevent.monkey.patch_all()
import gevent
import os
......
......@@ -6,11 +6,11 @@ import test__core_loop_run # this runs main tests, fails if signal() is not call
assert test__core_loop_run # pyflakes
from gevent.hub import signal as hub_signal
from gevent import signal
from gevent import signal as top_signal # pylint:disable=reimported
assert gevent.signal is hub_signal
assert gevent.signal is signal
assert gevent.signal is top_signal
assert hasattr(gevent.signal, 'signal')
s = signal(2, sys.stderr.write, 'INTERRUPT')
assert isinstance(s, signal)
s = top_signal(2, sys.stderr.write, 'INTERRUPT')
assert isinstance(s, top_signal)
assert isinstance(s, hub_signal)
......@@ -7,8 +7,8 @@ import time
import gevent
import gevent.core
import greentest
import greentest.flaky
import gevent.testing as greentest
import gevent.testing.flaky
#pylint: disable=protected-access
......@@ -83,7 +83,7 @@ class TestCoreStat(greentest.TestCase):
if reaction <= 0.0:
# Sigh. This is especially true on PyPy on Windows
raise greentest.flaky.FlakyTestRaceCondition(
raise gevent.testing.flaky.FlakyTestRaceCondition(
"Bad timer resolution (on Windows?), test is useless. Start %s, now %s" % (start, now))
self.assertGreaterEqual(
......
from __future__ import print_function
from gevent import config
import greentest
from greentest import TestCase
from greentest import LARGE_TIMEOUT
from greentest.sysinfo import CFFI_BACKEND
from greentest.flaky import reraises_flaky_timeout
import gevent.testing as greentest
from gevent.testing import TestCase
from gevent.testing import LARGE_TIMEOUT
from gevent.testing.sysinfo import CFFI_BACKEND
from gevent.testing.flaky import reraises_flaky_timeout
class Test(TestCase):
......@@ -94,7 +94,7 @@ class TestTimerResolution(Test):
# On CI, with *all* backends, sometimes we get timer values of
# 0.02 or higher.
@reraises_flaky_timeout(AssertionError)
def test_resolution(self):
def test_resolution(self): # pylint:disable=too-many-locals
# Make sure that having an active IO watcher
# doesn't badly throw off our timer resolution.
# (This was a specific problem with libuv)
......
from __future__ import absolute_import, print_function
import greentest
import gevent.testing as greentest
from gevent import config
from greentest.sysinfo import CFFI_BACKEND
from gevent.testing.sysinfo import CFFI_BACKEND
from gevent.core import READ # pylint:disable=no-name-in-module
from gevent.core import WRITE # pylint:disable=no-name-in-module
......
from __future__ import print_function
import doctest
import functools
import os
import re
import sys
import traceback
import unittest
import gevent
from gevent import socket
from greentest import walk_modules
from greentest import sysinfo
from gevent.testing import walk_modules
from gevent.testing import sysinfo
from gevent.testing import util
# Ignore tracebacks: ZeroDivisionError
def myfunction(*args, **kwargs):
def myfunction(*_args, **_kwargs):
pass
......@@ -44,29 +45,44 @@ if sysinfo.WIN:
'gevent.subprocess',
}
if __name__ == '__main__':
class Modules(object):
def __init__(self, allowed_modules):
self.allowed_modules = allowed_modules
self.modules = set()
for path, module in walk_modules():
self.add_module(module, path)
def add_module(self, name, path):
if self.allowed_modules and name not in self.allowed_modules:
return
if name in FORBIDDEN_MODULES:
return
self.modules.add((name, path))
def __bool__(self):
return bool(self.modules)
__nonzero__ = __bool__
def __iter__(self):
return iter(self.modules)
def main():
cwd = os.getcwd()
try:
allowed_modules = sys.argv[1:]
sys.path.append('.')
base = os.path.dirname(gevent.__file__)
print(base)
os.chdir('../..')
os.chdir(util.find_setup_py_above(__file__))
globs = {'myfunction': myfunction, 'gevent': gevent, 'socket': socket}
modules = set()
modules = Modules(allowed_modules)
def add_module(name, path):
if allowed_modules and name not in allowed_modules:
return
if name in FORBIDDEN_MODULES:
return
modules.add((name, path))
for path, module in walk_modules():
add_module(module, path)
add_module('setup', 'setup.py')
modules.add_module('setup', 'setup.py')
if not modules:
sys.exit('No modules found matching %s' % ' '.join(allowed_modules))
......@@ -88,18 +104,18 @@ if __name__ == '__main__':
with open(path, 'rb') as f:
contents = f.read()
if re.search(br'^\s*>>> ', contents, re.M):
try:
s = doctest.DocTestSuite(m, extraglobs=globs, checker=checker)
test_count = len(s._tests) # pylint: disable=W0212
print('%s (from %s): %s tests' % (m, path, test_count))
suite.addTest(s)
modules_count += 1
tests_count += test_count
except Exception:
traceback.print_exc()
sys.stderr.write('Failed to process %s\n\n' % path)
s = doctest.DocTestSuite(m, extraglobs=globs, checker=checker)
test_count = len(s._tests)
print('%s (from %s): %s tests' % (m, path, test_count))
suite.addTest(s)
modules_count += 1
tests_count += test_count
print('Total: %s tests in %s modules' % (tests_count, modules_count))
# TODO: Pass this off to unittest.main()
runner = unittest.TextTestRunner(verbosity=2)
runner.run(suite)
finally:
os.chdir(cwd)
if __name__ == '__main__':
main()
......@@ -6,7 +6,7 @@ import subprocess
if sys.argv[1:] == []:
os.environ['GEVENT_BACKEND'] = 'select'
popen = subprocess.Popen([sys.executable, 'test__environ.py', '1'])
popen = subprocess.Popen([sys.executable, __file__, '1'])
assert popen.wait() == 0, popen.poll()
else:
hub = gevent.get_hub()
......
......@@ -5,13 +5,13 @@ import weakref
import gevent
from gevent.event import Event, AsyncResult
import greentest
import gevent.testing as greentest
from greentest.six import xrange
from greentest.timing import AbstractGenericGetTestCase
from greentest.timing import AbstractGenericWaitTestCase
from greentest.timing import SMALL_TICK
from greentest.timing import SMALL_TICK_MAX_ADJ
from gevent.testing.six import xrange
from gevent.testing.timing import AbstractGenericGetTestCase
from gevent.testing.timing import AbstractGenericWaitTestCase
from gevent.testing.timing import SMALL_TICK
from gevent.testing.timing import SMALL_TICK_MAX_ADJ
DELAY = SMALL_TICK + SMALL_TICK_MAX_ADJ
......
from gevent.socket import create_connection, timeout
import greentest
import gevent.testing as greentest
import gevent
from greentest import util
from greentest import params
from gevent.testing import util
from gevent.testing import params
class Test(util.TestServer):
server = 'echoserver.py'
......
......@@ -8,8 +8,8 @@ from time import sleep
import gevent
from gevent.server import StreamServer
import greentest
from greentest import util
import gevent.testing as greentest
from gevent.testing import util
@greentest.skipOnLibuvOnCIOnPyPy("Timing issues sometimes lead to connection refused")
class Test(util.TestServer):
......
from gevent import monkey; monkey.patch_all(subprocess=True)
from gevent import monkey
monkey.patch_all(subprocess=True)
import sys
from gevent.server import DatagramServer
from unittest import TestCase
from greentest.util import run
from greentest import main
class Test_udp_client(TestCase):
from gevent.testing.util import run
from gevent.testing import util
from gevent.testing import main
class Test_udp_client(util.TestServer):
def test(self):
log = []
......@@ -18,7 +21,7 @@ class Test_udp_client(TestCase):
server.start()
try:
run([sys.executable, '-W', 'ignore', '-u', 'udp_client.py', 'Test_udp_client'],
timeout=10, cwd='../../examples/')
timeout=10, cwd=self.cwd)
finally:
server.close()
self.assertEqual(log, [b'Test_udp_client'])
......
import socket
from greentest import util
from greentest import main
from gevent.testing import util
from gevent.testing import main
class Test(util.TestServer):
......
......@@ -3,8 +3,8 @@ import os
import glob
import time
import greentest
from greentest import util
import gevent.testing as greentest
from gevent.testing import util
cwd = '../../examples/'
......
import gevent
import sys
import greentest
from greentest import six
from greentest import ExpectedException as ExpectedError
import gevent.testing as greentest
from gevent.testing import six
from gevent.testing import ExpectedException as ExpectedError
if not six.PY3:
sys.exc_clear()
......
import unittest
import warnings
from greentest.modules import walk_modules
from greentest import main
from greentest.sysinfo import NON_APPLICABLE_SUFFIXES
from gevent.testing.modules import walk_modules
from gevent.testing import main
from gevent.testing.sysinfo import NON_APPLICABLE_SUFFIXES
from greentest import six
from gevent.testing import six
class TestExec(unittest.TestCase):
......@@ -14,28 +15,25 @@ class TestExec(unittest.TestCase):
def make_exec_test(path, module):
def test(self):
#sys.stderr.write('%s %s\n' % (module, path))
def test(_):
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(recursive=True):
if module.endswith(NON_APPLICABLE_SUFFIXES):
continue
make_exec_test(path, module)
for path, module in walk_modules():
ignored = False
for x in NON_APPLICABLE_SUFFIXES:
if module.endswith(x):
ignored = True
break
if ignored:
continue
make_exec_test(path, module)
make_all_tests()
if __name__ == '__main__':
main()
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
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