Commit e5b881b7 authored by Jason Madden's avatar Jason Madden

Refactor greentest.py into a package.

parent e012980a
......@@ -58,3 +58,49 @@ class wrap_errors(object):
def __getattr__(self, name):
return getattr(self.__func, name)
def dump_stacks():
"""
Request information about the running threads of the current process.
This is a debugging utility. Its output has no guarantees other than being
intended for human consumption.
:return: A sequence of text lines detailing the stacks of running
threads and greenlets. (One greenlet will duplicate one thread,
the current thread and greenlet.)
.. versionadded:: 1.3a1
"""
dump = []
# threads
import threading # Late import this stuff because it may get monkey-patched
import traceback
import sys
import gc
from greenlet import greenlet
threads = {th.ident: th.name for th in threading.enumerate()}
for thread, frame in sys._current_frames().items():
dump.append('Thread 0x%x (%s)\n' % (thread, threads.get(thread)))
dump.append(''.join(traceback.format_stack(frame)))
dump.append('\n')
# greenlets
# if greenlet is present, let's dump each greenlet stack
# Use the gc module to inspect all objects to find the greenlets
# since there isn't a global registry
for ob in gc.get_objects():
if not isinstance(ob, greenlet):
continue
if not ob:
continue # not running anymore or not started
dump.append('Greenlet %s\n' % ob)
dump.append(''.join(traceback.format_stack(ob.gr_frame)))
dump.append('\n')
return dump
This diff is collapsed.
# Copyright (c) 2008-2009 AG Projects
# Copyright 2018 gevent community
# Author: Denis Bilenko
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# 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 PY2
from greentest.sysinfo import PY3
from greentest.sysinfo import PY34
from greentest.sysinfo import PY36
from greentest.sysinfo import PY37
from greentest.sysinfo import PYPY
from greentest.sysinfo import PYPY3
from greentest.sysinfo import PLATFORM_SPECIFIC_SUFFIXES
from greentest.sysinfo import NON_APPLICABLE_SUFFIXES
from greentest.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 greentest.sysinfo import EXPECT_POOR_TIMER_RESOLUTION
from greentest.sysinfo import CONN_ABORTED_ERRORS
from greentest.skipping import skipOnWindows
from greentest.skipping import skipOnAppVeyor
from greentest.skipping import skipOnPyPy3OnCI
from greentest.skipping import skipOnPyPy
from greentest.skipping import skipOnPyPy3
from greentest.skipping import skipIf
from greentest.skipping import skipOnLibuv
from greentest.skipping import skipOnLibuvOnCI
from greentest.skipping import skipOnLibuvOnCIOnPyPy
from greentest.exception import ExpectedException
from greentest.leakcheck import ignores_leakcheck
from greentest.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 greentest.params import DEFAULT_SOCKET_TIMEOUT
from greentest.params import DEFAULT_XPC_SOCKET_TIMEOUT
main = unittest.main
from greentest.hub import QuietHub
import gevent.hub
gevent.hub.Hub = QuietHub
from greentest.sockets import bind_and_listen
from greentest.sockets import tcp_listener
from greentest.openfiles import get_number_open_files
from greentest.openfiles import get_open_files
from greentest.testcase import TestCase
from greentest.timing import AbstractGenericGetTestCase as GenericGetTestCase
from greentest.timing import AbstractGenericWaitTestCase as GenericWaitTestCase
from greentest.modules import walk_modules
BaseTestCase = unittest.TestCase
# Copyright (c) 2018 gevent community
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
# THE SOFTWARE.
from functools import wraps
def wrap_error_fatal(method):
import gevent
SYSTEM_ERROR = gevent.get_hub().SYSTEM_ERROR
@wraps(method)
def wrapper(self, *args, **kwargs):
# XXX should also be able to do gevent.SYSTEM_ERROR = object
# which is a global default to all hubs
gevent.get_hub().SYSTEM_ERROR = object
try:
return method(self, *args, **kwargs)
finally:
gevent.get_hub().SYSTEM_ERROR = SYSTEM_ERROR
return wrapper
def wrap_restore_handle_error(method):
import gevent
old = gevent.get_hub().handle_error
@wraps(method)
def wrapper(self, *args, **kwargs):
try:
return method(self, *args, **kwargs)
finally:
gevent.get_hub().handle_error = old
if self.peek_error()[0] is not None:
gevent.getcurrent().throw(*self.peek_error()[1:])
return wrapper
# Copyright (c) 2018 gevent community
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
# THE SOFTWARE.
from __future__ import absolute_import, print_function, division
class ExpectedException(Exception):
"""An exception whose traceback should be ignored by the hub"""
# Copyright (c) 2018 gevent community
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
# THE SOFTWARE.
from __future__ import absolute_import, print_function, division
import sys
import unittest
from gevent.util import dump_stacks
from greentest import sysinfo
from greentest import six
# The next exceptions allow us to raise them in a highly
# greppable way so that we can debug them later.
class FlakyTest(unittest.SkipTest):
"""
A unittest exception that causes the test to be skipped when raised.
Use this carefully, it is a code smell and indicates an undebugged problem.
"""
class FlakyTestRaceCondition(FlakyTest):
"""
Use this when the flaky test is definitely caused by a race condition.
"""
class FlakyTestTimeout(FlakyTest):
"""
Use this when the flaky test is definitely caused by an
unexpected timeout.
"""
class FlakyTestCrashes(FlakyTest):
"""
Use this when the test sometimes crashes.
"""
def reraiseFlakyTestRaceCondition():
six.reraise(*sys.exc_info())
reraiseFlakyTestTimeout = reraiseFlakyTestRaceCondition
reraiseFlakyTestRaceConditionLibuv = reraiseFlakyTestRaceCondition
reraiseFlakyTestTimeoutLibuv = reraiseFlakyTestRaceCondition
if sysinfo.RUNNING_ON_CI:
# pylint: disable=function-redefined
def reraiseFlakyTestRaceCondition():
six.reraise(FlakyTestRaceCondition,
FlakyTestRaceCondition('\n'.join(dump_stacks())),
sys.exc_info()[2])
def reraiseFlakyTestTimeout():
six.reraise(FlakyTestTimeout,
FlakyTestTimeout(),
sys.exc_info()[2])
if sysinfo.LIBUV:
reraiseFlakyTestRaceConditionLibuv = reraiseFlakyTestRaceCondition
reraiseFlakyTestTimeoutLibuv = reraiseFlakyTestTimeout
# Copyright (c) 2018 gevent community
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
# THE SOFTWARE.
from __future__ import absolute_import, print_function, division
from gevent.hub import Hub
from greentest.exception import ExpectedException
class QuietHub(Hub):
EXPECTED_TEST_ERROR = (ExpectedException,)
def handle_error(self, context, type, value, tb):
if issubclass(type, self.EXPECTED_TEST_ERROR):
# Don't print these to cut down on the noise in the test logs
return
return Hub.handle_error(self, context, type, value, tb)
# Copyright (c) 2018 gevent community
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
# THE SOFTWARE.
import gc
import collections
import types
import gevent.core
def ignores_leakcheck(func):
func.ignore_leakcheck = True
return func
def wrap_refcount(method):
if getattr(method, 'ignore_leakcheck', False):
return method
# Some builtin things that we ignore
IGNORED_TYPES = (tuple, dict, types.FrameType, types.TracebackType)
try:
callback_kind = gevent.core.callback
except AttributeError:
# Must be using FFI.
from gevent._ffi.callback import callback as callback_kind
def type_hist():
d = collections.defaultdict(int)
for x in gc.get_objects():
k = type(x)
if k in IGNORED_TYPES:
continue
if k == callback_kind and x.callback is None and x.args is None:
# these represent callbacks that have been stopped, but
# the event loop hasn't cycled around to run them. The only
# known cause of this is killing greenlets before they get a chance
# to run for the first time.
continue
d[k] += 1
return d
def report_diff(a, b):
diff_lines = []
for k, v in sorted(a.items(), key=lambda i: i[0].__name__):
if b[k] != v:
diff_lines.append("%s: %s != %s" % (k, v, b[k]))
if not diff_lines:
return None
diff = '\n'.join(diff_lines)
return diff
@wraps(method)
def wrapper(self, *args, **kwargs):
gc.collect()
gc.collect()
gc.collect()
deltas = []
d = None
gc.disable()
try:
while True:
# Grab current snapshot
hist_before = type_hist()
d = sum(hist_before.values())
self.setUp()
try:
method(self, *args, **kwargs)
finally:
self.tearDown()
# Grab post snapshot
if 'urlparse' in sys.modules:
sys.modules['urlparse'].clear_cache()
if 'urllib.parse' in sys.modules:
sys.modules['urllib.parse'].clear_cache()
hist_after = type_hist()
d = sum(hist_after.values()) - d
deltas.append(d)
# Reset and check for cycles
gc.collect()
if gc.garbage:
raise AssertionError("Generated uncollectable garbage %r" % (gc.garbage,))
# the following configurations are classified as "no leak"
# [0, 0]
# [x, 0, 0]
# [... a, b, c, d] where a+b+c+d = 0
#
# the following configurations are classified as "leak"
# [... z, z, z] where z > 0
if deltas[-2:] == [0, 0] and len(deltas) in (2, 3):
break
elif deltas[-3:] == [0, 0, 0]:
break
elif len(deltas) >= 4 and sum(deltas[-4:]) == 0:
break
elif len(deltas) >= 3 and deltas[-1] > 0 and deltas[-1] == deltas[-2] and deltas[-2] == deltas[-3]:
diff = report_diff(hist_before, hist_after)
raise AssertionError('refcount increased by %r\n%s' % (deltas, diff))
# OK, we don't know for sure yet. Let's search for more
if sum(deltas[-3:]) <= 0 or sum(deltas[-4:]) <= 0 or deltas[-4:].count(0) >= 2:
# this is suspicious, so give a few more runs
limit = 11
else:
limit = 7
if len(deltas) >= limit:
raise AssertionError('refcount increased by %r\n%s' % (deltas, report_diff(hist_before, hist_after)))
finally:
gc.enable()
self.skipTearDown = True
return wrapper
# Copyright (c) 2018 gevent community
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
# THE SOFTWARE.
from __future__ import absolute_import, print_function, division
import os.path
import gevent
from greentest import sysinfo
from greentest import six
OPTIONAL_MODULES = ['resolver_ares']
def walk_modules(basedir=None, modpath=None, include_so=False, recursive=False):
# pylint:disable=too-many-branches
if sysinfo.PYPY:
include_so = False
if basedir is None:
basedir = os.path.dirname(gevent.__file__)
if modpath is None:
modpath = 'gevent.'
else:
if modpath is None:
modpath = ''
for fn in sorted(os.listdir(basedir)):
path = os.path.join(basedir, fn)
if os.path.isdir(path):
if not recursive:
continue
pkg_init = os.path.join(path, '__init__.py')
if os.path.exists(pkg_init):
yield pkg_init, modpath + fn
for p, m in walk_modules(path, modpath + fn + "."):
yield p, m
continue
if fn.endswith('.py'):
x = fn[:-3]
if x.endswith('_d'):
x = x[:-2]
if x in ['__init__', 'core', 'ares', '_util', '_semaphore',
'corecffi', '_corecffi', '_corecffi_build']:
continue
if x in OPTIONAL_MODULES:
try:
six.exec_("import %s" % x, {})
except ImportError:
continue
yield path, modpath + x
elif include_so and fn.endswith(sysinfo.SHARED_OBJECT_EXTENSION):
if '.pypy-' in fn:
continue
if fn.endswith('_d.so'):
yield path, modpath + fn[:-5]
else:
yield path, modpath + fn[:-3]
# Copyright (c) 2018 gevent community
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
# THE SOFTWARE.
from __future__ import absolute_import, print_function, division
import os
import unittest
import re
from greentest import sysinfo
# Linux/OS X/BSD platforms can implement this by calling out to lsof
if sysinfo.WIN:
def _run_lsof():
raise unittest.SkipTest("lsof not expected on Windows")
else:
def _run_lsof():
import tempfile
pid = os.getpid()
fd, tmpname = tempfile.mkstemp('get_open_files')
os.close(fd)
lsof_command = 'lsof -p %s > %s' % (pid, tmpname)
if os.system(lsof_command):
# XXX: This prints to the console an annoying message: 'lsof is not recognized'
raise unittest.SkipTest("lsof failed")
with open(tmpname) as fobj:
data = fobj.read().strip()
os.remove(tmpname)
return data
def default_get_open_files(pipes=False):
data = _run_lsof()
results = {}
for line in data.split('\n'):
line = line.strip()
if not line or line.startswith("COMMAND"):
# Skip header and blank lines
continue
split = re.split(r'\s+', line)
_command, _pid, _user, fd = split[:4]
# Pipes (on OS X, at least) get an fd like "3" while normal files get an fd like "1u"
if fd[:-1].isdigit() or fd.isdigit():
if not pipes and fd[-1].isdigit():
continue
fd = int(fd[:-1]) if not fd[-1].isdigit() else int(fd)
if fd in results:
params = (fd, line, split, results.get(fd), data)
raise AssertionError('error when parsing lsof output: duplicate fd=%r\nline=%r\nsplit=%r\nprevious=%r\ndata:\n%s' % params)
results[fd] = line
if not results:
raise AssertionError('failed to parse lsof:\n%s' % (data, ))
results['data'] = data
return results
def default_get_number_open_files():
if os.path.exists('/proc/'):
# 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
lsof_get_open_files = default_get_open_files
try:
# psutil import subprocess which on Python 3 imports selectors.
# This can expose issues with monkey-patching.
import psutil
except ImportError:
get_open_files = default_get_open_files
get_number_open_files = default_get_number_open_files
else:
# If psutil is available (it is cross-platform) use that.
# It is *much* faster than shelling out to lsof each time
# (Running 14 tests takes 3.964s with lsof and 0.046 with psutil)
# However, it still doesn't completely solve the issue on Windows: fds are reported
# as -1 there, so we can't fully check those.
def get_open_files():
"""
Return a list of popenfile and pconn objects.
Note that other than `fd`, they have different attributes.
.. important:: If you want to find open sockets, on Windows
and linux, it is important that the socket at least be listening
(socket.listen(1)). Unlike the lsof implementation, this will only
return sockets in a state like that.
"""
results = dict()
process = psutil.Process()
results['data'] = process.open_files() + process.connections('all')
for x in results['data']:
results[x.fd] = x
results['data'] += ['From psutil', process]
return results
def get_number_open_files():
process = psutil.Process()
try:
return process.num_fds()
except AttributeError:
# num_fds is unix only. Is num_handles close enough on Windows?
return 0
# Copyright (c) 2018 gevent community
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
# 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 RUNNING_ON_TRAVIS
from greentest.sysinfo import EXPECT_POOR_TIMER_RESOLUTION
# 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
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
if PYPY and LIBUV:
# slow and flaky timeouts
LOCAL_TIMEOUT = CI_TIMEOUT
else:
LOCAL_TIMEOUT = 1
LARGE_TIMEOUT = max(LOCAL_TIMEOUT, CI_TIMEOUT)
DEFAULT_LOCAL_HOST_ADDR = 'localhost'
DEFAULT_LOCAL_HOST_ADDR6 = DEFAULT_LOCAL_HOST_ADDR
DEFAULT_BIND_ADDR = ''
if RUNNING_ON_TRAVIS:
# As of November 2017 (probably Sept or Oct), after a
# Travis upgrade, using "localhost" no longer works,
# producing 'OSError: [Errno 99] Cannot assign
# requested address'. This is apparently something to do with
# docker containers. Sigh.
DEFAULT_LOCAL_HOST_ADDR = '127.0.0.1'
DEFAULT_LOCAL_HOST_ADDR6 = '::1'
# Likewise, binding to '' appears to work, but it cannot be
# connected to with the same error.
DEFAULT_BIND_ADDR = '127.0.0.1'
# For in-process sockets
DEFAULT_SOCKET_TIMEOUT = 0.1 if not EXPECT_POOR_TIMER_RESOLUTION else 2.0
# For cross-process sockets
DEFAULT_XPC_SOCKET_TIMEOUT = 2.0 if not EXPECT_POOR_TIMER_RESOLUTION else 4.0
# Copyright (c) 2018 gevent community
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
# THE SOFTWARE.
from __future__ import absolute_import, print_function, division
import unittest
from greentest import sysinfo
def _do_not_skip(reason):
assert reason
def dec(f):
return f
return dec
if sysinfo.WIN:
skipOnWindows = unittest.skip
else:
skipOnWindows = _do_not_skip
if sysinfo.RUNNING_ON_APPVEYOR:
# See comments scattered around about timeouts and the timer
# resolution available on appveyor (lots of jitter). this
# seems worse with the 62-bit builds.
# Note that we skip/adjust these tests only on AppVeyor, not
# win32---we don't think there's gevent related problems but
# environment related problems. These can be tested and debugged
# separately on windows in a more stable environment.
skipOnAppVeyor = unittest.skip
else:
skipOnAppVeyor = _do_not_skip
if sysinfo.PYPY3 and sysinfo.RUNNING_ON_CI:
# Same as above, for PyPy3.3-5.5-alpha and 3.5-5.7.1-beta and 3.5-5.8
skipOnPyPy3OnCI = unittest.skip
else:
skipOnPyPy3OnCI = _do_not_skip
if sysinfo.PYPY:
skipOnPyPy = unittest.skip
else:
skipOnPyPy = _do_not_skip
if sysinfo.PYPY3:
skipOnPyPy3 = unittest.skip
else:
skipOnPyPy3 = _do_not_skip
skipIf = unittest.skipIf
skipOnLibuv = _do_not_skip
skipOnLibuvOnCI = _do_not_skip
skipOnLibuvOnCIOnPyPy = _do_not_skip
if sysinfo.LIBUV:
skipOnLibuv = unittest.skip
if sysinfo.RUNNING_ON_CI:
skipOnLibuvOnCI = unittest.skip
if sysinfo.PYPY:
skipOnLibuvOnCIOnPyPy = unittest.skip
# Copyright (c) 2018 gevent community
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
# THE SOFTWARE.
from __future__ import absolute_import, print_function, division
def bind_and_listen(sock, address=('', 0), backlog=50, reuse_addr=True):
from socket import SOL_SOCKET, SO_REUSEADDR, error
if reuse_addr:
try:
sock.setsockopt(SOL_SOCKET, SO_REUSEADDR,
sock.getsockopt(SOL_SOCKET, SO_REUSEADDR) | 1)
except error:
pass
sock.bind(address)
sock.listen(backlog)
def tcp_listener(address, backlog=50, reuse_addr=True):
"""A shortcut to create a TCP socket, bind it and put it into listening state."""
from gevent import socket
sock = socket.socket()
bind_and_listen(sock, address, backlog=backlog, reuse_addr=reuse_addr)
return sock
# Copyright (c) 2018 gevent community
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
# THE SOFTWARE.
from __future__ import absolute_import, print_function, division
from functools import wraps
from gevent.hub import _get_hub
from greentest.hub import QuietHub
from patched_tests_setup import get_switch_expected
def wrap_switch_count_check(method):
@wraps(method)
def wrapper(self, *args, **kwargs):
initial_switch_count = getattr(_get_hub(), 'switch_count', None)
self.switch_expected = getattr(self, 'switch_expected', True)
if initial_switch_count is not None:
fullname = getattr(self, 'fullname', None)
if self.switch_expected == 'default' and fullname:
self.switch_expected = get_switch_expected(fullname)
result = method(self, *args, **kwargs)
if initial_switch_count is not None and self.switch_expected is not None:
switch_count = _get_hub().switch_count - initial_switch_count
if self.switch_expected is True:
assert switch_count >= 0
if not switch_count:
raise AssertionError('%s did not switch' % fullname)
elif self.switch_expected is False:
if switch_count:
raise AssertionError('%s switched but not expected to' % fullname)
else:
raise AssertionError('Invalid value for switch_expected: %r' % (self.switch_expected, ))
return result
return wrapper
class CountingHub(QuietHub):
switch_count = 0
def switch(self, *args):
# pylint:disable=arguments-differ
self.switch_count += 1
return QuietHub.switch(self, *args)
# Copyright (c) 2018 gevent community
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
# THE SOFTWARE.
import os
import sys
import gevent.core
PYPY = hasattr(sys, 'pypy_version_info')
VERBOSE = sys.argv.count('-v') > 1
WIN = sys.platform.startswith("win")
LINUX = sys.platform.startswith('linux')
# XXX: Formalize this better
LIBUV = os.getenv('GEVENT_CORE_CFFI_ONLY') == 'libuv' or (PYPY and WIN) or hasattr(gevent.core, 'libuv')
CFFI_BACKEND = bool(os.getenv('GEVENT_CORE_CFFI_ONLY')) or PYPY
if '--debug-greentest' in sys.argv:
sys.argv.remove('--debug-greentest')
DEBUG = True
else:
DEBUG = False
RUN_LEAKCHECKS = os.getenv('GEVENTTEST_LEAKCHECK')
# 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']
if WIN:
PLATFORM_SPECIFIC_SUFFIXES.append('posix')
PY2 = None
PY3 = None
PY34 = None
PY36 = None
PY37 = None
NON_APPLICABLE_SUFFIXES = []
if sys.version_info[0] == 3:
# Python 3
NON_APPLICABLE_SUFFIXES.extend(('2', '279'))
PY2 = False
PY3 = True
if sys.version_info[1] >= 4:
PY34 = True
if sys.version_info[1] >= 6:
PY36 = True
if sys.version_info[1] >= 7:
PY37 = True
elif sys.version_info[0] == 2:
# Any python 2
PY3 = False
PY2 = True
NON_APPLICABLE_SUFFIXES.append('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')
PYPY3 = PYPY and PY3
if WIN:
NON_APPLICABLE_SUFFIXES.append("posix")
# This is intimately tied to FileObjectPosix
NON_APPLICABLE_SUFFIXES.append("fileobject2")
SHARED_OBJECT_EXTENSION = ".pyd"
else:
SHARED_OBJECT_EXTENSION = ".so"
RUNNING_ON_TRAVIS = os.environ.get('TRAVIS')
RUNNING_ON_APPVEYOR = os.environ.get('APPVEYOR')
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')
EXPECT_POOR_TIMER_RESOLUTION = PYPY3 or RUNNING_ON_APPVEYOR or (LIBUV and PYPY)
CONN_ABORTED_ERRORS = []
try:
from errno import WSAECONNABORTED
CONN_ABORTED_ERRORS.append(WSAECONNABORTED)
except ImportError:
pass
from errno import ECONNRESET
CONN_ABORTED_ERRORS.append(ECONNRESET)
CONN_ABORTED_ERRORS = frozenset(CONN_ABORTED_ERRORS)
This diff is collapsed.
This diff is collapsed.
# Copyright (c) 2018 gevent community
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
# THE SOFTWARE.
import time
import gevent
from greentest import sysinfo
from greentest import leakcheck
from greentest.testcase import TestCase
class _DelayWaitMixin(object):
_default_wait_timeout = 0.01
_default_delay_min_adj = 0.001
if not sysinfo.RUNNING_ON_APPVEYOR:
_default_delay_max_adj = 0.11
else:
# Timing resolution is extremely poor on Appveyor
# and subject to jitter.
_default_delay_max_adj = 1.5
def wait(self, timeout):
raise NotImplementedError('override me in subclass')
def _check_delay_bounds(self, timeout, delay,
delay_min_adj=None,
delay_max_adj=None):
delay_min_adj = self._default_delay_min_adj if not delay_min_adj else delay_min_adj
delay_max_adj = self._default_delay_max_adj if not delay_max_adj else delay_max_adj
self.assertGreaterEqual(delay, timeout - delay_min_adj)
self.assertLess(delay, timeout + delay_max_adj)
def _wait_and_check(self, timeout=None):
if timeout is None:
timeout = self._default_wait_timeout
# gevent.timer instances have a 'seconds' attribute,
# otherwise it's the raw number
seconds = getattr(timeout, 'seconds', timeout)
start = time.time()
try:
result = self.wait(timeout)
finally:
self._check_delay_bounds(seconds, time.time() - start,
self._default_delay_min_adj,
self._default_delay_max_adj)
return result
def test_outer_timeout_is_not_lost(self):
timeout = gevent.Timeout.start_new(0.001, ref=False)
try:
with self.assertRaises(gevent.Timeout) as exc:
self.wait(timeout=1)
self.assertIs(exc.exception, timeout)
finally:
timeout.cancel()
class AbstractGenericWaitTestCase(_DelayWaitMixin, TestCase):
# pylint:disable=abstract-method
_default_wait_timeout = 0.2
_default_delay_min_adj = 0.1
if not sysinfo.RUNNING_ON_APPVEYOR:
_default_delay_max_adj = 0.11
else:
# Timing resolution is very poor on Appveyor
# and subject to jitter
_default_delay_max_adj = 1.5
@leakcheck.ignores_leakcheck # waiting checks can be very sensitive to timing
def test_returns_none_after_timeout(self):
result = self._wait_and_check()
# join and wait simply return after timeout expires
self.assertIsNone(result)
class AbstractGenericGetTestCase(_DelayWaitMixin, TestCase):
# pylint:disable=abstract-method
Timeout = gevent.Timeout
def cleanup(self):
pass
def test_raises_timeout_number(self):
with self.assertRaises(self.Timeout):
self._wait_and_check(timeout=0.01)
# get raises Timeout after timeout expired
self.cleanup()
def test_raises_timeout_Timeout(self):
timeout = gevent.Timeout(self._default_wait_timeout)
try:
self._wait_and_check(timeout=timeout)
except gevent.Timeout as ex:
self.assertIs(ex, timeout)
self.cleanup()
def test_raises_timeout_Timeout_exc_customized(self):
error = RuntimeError('expected error')
timeout = gevent.Timeout(self._default_wait_timeout, exception=error)
with self.assertRaises(RuntimeError) as exc:
self._wait_and_check(timeout=timeout)
self.assertIs(exc.exception, error)
self.cleanup()
import sys
import os
import _six as six
from greentest import six
import traceback
import unittest
import threading
......
......@@ -5,13 +5,13 @@ try:
except ImportError:
import urllib2
from unittest import SkipTest
import util
import socket
import ssl
from greentest import DEFAULT_XPC_SOCKET_TIMEOUT
from greentest import main
from greentest import util
class Test_wsgiserver(util.TestServer):
server = 'wsgiserver.py'
......
import sys
import os
import glob
import util
import atexit
# subprocess: include in subprocess tests
from greentest import util
TIMEOUT = 120
directory = '%s.%s' % sys.version_info[:2]
......
"""Check __all__, __implements__, __extensions__, __imports__ of the modules"""
from __future__ import print_function
import _six as six
from greentest import six
import sys
import unittest
import types
from greentest import walk_modules
from greentest import PLATFORM_SPECIFIC_SUFFIXES
from greentest.modules import walk_modules
from greentest.sysinfo import PLATFORM_SPECIFIC_SUFFIXES
MAPPING = {
......@@ -216,6 +216,8 @@ are missing from %r:
self.check_extensions_actually_extend()
self.check_completeness()
path = modname = orig_modname = None
for path, modname in walk_modules(include_so=True):
orig_modname = modname
modname = modname.replace('gevent.', '').split('.')[0]
......
import greentest
import gevent
from gevent.event import Event, AsyncResult
from _six import xrange
from greentest.six import xrange
DELAY = 0.01
......
......@@ -2,7 +2,7 @@ from gevent.socket import create_connection, timeout
import greentest
import gevent
import util
from greentest import util
class Test(util.TestServer):
server = 'echoserver.py'
......
......@@ -8,7 +8,7 @@ from time import sleep
import gevent
from gevent.server import StreamServer
import util
from greentest import util
class Test(util.TestServer):
......@@ -23,16 +23,16 @@ class Test(util.TestServer):
def after(self):
if sys.platform == 'win32':
assert self.popen.poll() is not None
self.assertIsNotNone(self.popen.poll())
else:
self.assertEqual(self.popen.poll(), 0)
def _run_all_tests(self):
log = []
def handle(socket, address):
def handle(sock, _address):
while True:
data = socket.recv(1024)
data = sock.recv(1024)
print('got %r' % data)
if not data:
break
......@@ -47,8 +47,7 @@ class Test(util.TestServer):
# On Windows, SIGTERM actually abruptly terminates the process;
# it can't be caught. However, CTRL_C_EVENT results in a KeyboardInterrupt
# being raised, so we can shut down properly.
self.popen.send_signal(getattr(signal, 'CTRL_C_EVENT') if hasattr(signal, 'CTRL_C_EVENT')
else signal.SIGTERM)
self.popen.send_signal(getattr(signal, 'CTRL_C_EVENT', signal.SIGTERM))
sleep(0.1)
conn.sendall(b'msg2')
......
from gevent import monkey; monkey.patch_all(subprocess=True)
import sys
from gevent.server import DatagramServer
from unittest import TestCase, main
from util import run
from unittest import TestCase
from greentest.util import run
from greentest import main
class Test_udp_client(TestCase):
......
import socket
from unittest import main
import util
from greentest import util
from greentest import main
class Test(util.TestServer):
......@@ -10,7 +11,7 @@ class Test(util.TestServer):
sock = socket.socket(type=socket.SOCK_DGRAM)
sock.connect(('127.0.0.1', 9000))
sock.send(b'Test udp_server')
data, address = sock.recvfrom(8192)
data, _address = sock.recvfrom(8192)
self.assertEqual(data, b'Received 15 bytes')
sock.close()
......
......@@ -2,7 +2,8 @@ import sys
import os
import glob
import time
import util
from greentest import util
cwd = '../../examples/'
......
import gevent
import sys
import greentest
import _six as six
from greentest import six
if not six.PY3:
sys.exc_clear()
......
from greentest import walk_modules, BaseTestCase, main, NON_APPLICABLE_SUFFIXES
import _six as six
import unittest
from greentest.modules import walk_modules
from greentest import main
from greentest.sysinfo import NON_APPLICABLE_SUFFIXES
class TestExec(BaseTestCase):
from greentest import six
class TestExec(unittest.TestCase):
pass
......
# test for issue #210
from gevent import core
from util import alarm
from greentest.util import alarm
alarm(1)
......
import gevent
import greentest
from _six import xrange
from greentest.six import xrange
class appender(object):
......
import sys
import _six as six
from greentest import six
from os import pipe
import gevent
from gevent import os
from greentest import TestCase, main, CI_TIMEOUT
from greentest import TestCase, main, LARGE_TIMEOUT
from gevent import Greenlet, joinall
class TestOS_tp(TestCase):
__timeout__ = CI_TIMEOUT
__timeout__ = LARGE_TIMEOUT
def pipe(self):
return pipe()
......@@ -83,7 +83,7 @@ if hasattr(os, 'fork_and_watch'):
class TestForkAndWatch(TestCase):
__timeout__ = CI_TIMEOUT
__timeout__ = LARGE_TIMEOUT
def test_waitpid_all(self):
# Cover this specific case.
......
......@@ -7,7 +7,7 @@ from gevent.timeout import Timeout
import greentest
import random
from greentest import ExpectedException
import _six as six
from greentest import six
import unittest
......
import _six as six
from greentest import six
import sys
import os
import errno
......
import gevent
from util import alarm
from greentest.util import alarm
alarm(3)
......
......@@ -8,7 +8,7 @@ import time
import unittest
import greentest
from functools import wraps
import _six as six
from greentest import six
# we use threading on purpose so that we can test both regular and gevent sockets with the same code
from threading import Thread as _Thread
......
#!/usr/bin/python
# -*- coding: utf-8 -*-
import _six as six
import re
import greentest
import unittest
......@@ -8,8 +8,9 @@ import socket
from time import time
import gevent
import gevent.socket as gevent_socket
from util import log
from _six import xrange
from greentest.util import log
from greentest import six
from greentest.six import xrange
resolver = gevent.get_hub().resolver
......
import sys
from gevent.subprocess import Popen
from util import alarm
from greentest.util import alarm
alarm(3)
......
import sys
from time import time, sleep
import contextlib
import random
import weakref
import greentest
......@@ -7,16 +8,27 @@ import gevent.threadpool
from gevent.threadpool import ThreadPool
import gevent
from greentest import ExpectedException
import _six as six
from greentest import six
import gc
PYPY = hasattr(sys, 'pypy_version_info')
@contextlib.contextmanager
def disabled_gc():
was_enabled = gc.isenabled()
gc.disable()
try:
yield
finally:
if was_enabled:
gc.enable()
class TestCase(greentest.TestCase):
# These generally need more time
__timeout__ = greentest.CI_TIMEOUT
__timeout__ = greentest.LARGE_TIMEOUT
pool = None
def cleanup(self):
......@@ -402,7 +414,7 @@ class TestRef(TestCase):
func = obj.func
del obj
with greentest.disabled_gc():
with disabled_gc():
# we do this:
# result = func(Object(), kwarg1=Object())
# but in a thread pool and see that arguments', result's and func's references are not leaked
......
......@@ -3,7 +3,7 @@ import gevent
import gevent.core
from gevent.event import Event
from time import time
from _six import xrange
from greentest.six import xrange
SMALL = 0.1
......
# testing gevent's Event, Lock, RLock, Semaphore, BoundedSemaphore with standard test_threading
from __future__ import print_function
from _six import xrange
from greentest.six import xrange
import greentest
setup_ = '''from gevent import monkey; monkey.patch_all()
......
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