Commit 4fae43f1 authored by Jason Madden's avatar Jason Madden

Fix test__core_timer.py by not destroying the default loop. D'oh!

Before I realized that was the root cause, I refactored to avoid
starting the hub greenlet *at all*, and that also fixed the problem.

The problem was that some versions of CPython using the libev-cext
loop (and only that one) would crash garbage collecting a
greenlet (presumably the hub greenlet, which was attached to a
destroyed loop):

0   libsystem_kernel.dylib        	0x00007fff66455e3e __pthread_kill + 10
1   libsystem_pthread.dylib       	0x00007fff66594150 pthread_kill + 333
2   libsystem_c.dylib             	0x00007fff663648fe raise + 26
3   libsystem_platform.dylib      	0x00007fff66587f5a _sigtramp + 26
4   ???                           	000000000000000000 0 + 0
5   greenlet.cpython-35m-darwin.so	0x000000010d76b297 green_clear + 183
6   org.python.python             	0x000000010c707e0c collect + 1824
7   org.python.python             	0x000000010c7076e3 _PyGC_CollectNoFail + 43
8   org.python.python             	0x000000010c6e81d4 PyImport_Cleanup + 968
9   org.python.python             	0x000000010c6f1b49 Py_Finalize + 92
10  org.python.python             	0x000000010c6f20d5 Py_Exit + 13
11  org.python.python             	0x000000010c6f4631 handle_system_exit + 320
12  org.python.python             	0x000000010c6f42a1 PyErr_PrintEx + 42

We should take a look at that and see if we can do something more graceful.
parent ecd1bd10
......@@ -45,43 +45,43 @@ prospector:
lint: prospector
test_prelim:
which ${PYTHON}
${PYTHON} --version
${PYTHON} -c 'import greenlet; print(greenlet, greenlet.__version__)'
${PYTHON} -c 'import gevent.core; print(gevent.core.loop)'
${PYTHON} -c 'import gevent.ares; print(gevent.ares)'
make bench
@which ${PYTHON}
@${PYTHON} --version
@${PYTHON} -c 'import greenlet; print(greenlet, greenlet.__version__)'
@${PYTHON} -c 'import gevent.core; print(gevent.core.loop)'
@${PYTHON} -c 'import gevent.ares; print(gevent.ares)'
@make bench
# Folding from https://github.com/travis-ci/travis-rubies/blob/9f7962a881c55d32da7c76baefc58b89e3941d91/build.sh#L38-L44
basictest: test_prelim
${PYTHON} scripts/travis.py fold_start basictest "Running basic tests"
@${PYTHON} scripts/travis.py fold_start basictest "Running basic tests"
cd src/greentest && GEVENT_RESOLVER=thread ${PYTHON} testrunner.py --config known_failures.py --quiet
${PYTHON} scripts/travis.py fold_end basictest
@${PYTHON} scripts/travis.py fold_end basictest
alltest: basictest
${PYTHON} scripts/travis.py fold_start ares "Running c-ares tests"
@${PYTHON} scripts/travis.py fold_start ares "Running c-ares tests"
cd src/greentest && GEVENT_RESOLVER=ares GEVENTARES_SERVERS=8.8.8.8 ${PYTHON} testrunner.py --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"
@${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
${PYTHON} scripts/travis.py fold_end dnspython
@${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.
${PYTHON} scripts/travis.py fold_start thread "Running GEVENT_FILE=thread tests"
@${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
${PYTHON} scripts/travis.py fold_end thread
@${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"
@${PYTHON} scripts/travis.py fold_start default "Testing default backend"
GEVENTTEST_COVERAGE=1 make alltest
${PYTHON} scripts/travis.py fold_end default
@${PYTHON} scripts/travis.py fold_end default
GEVENTTEST_COVERAGE=1 make cffibackendtest
# because we set parallel=true, each run produces new and different coverage files; they all need
# to be combined
......@@ -89,17 +89,17 @@ allbackendtest:
cffibackendtest:
${PYTHON} scripts/travis.py fold_start libuv "Testing libuv backend"
@${PYTHON} scripts/travis.py fold_start libuv "Testing libuv backend"
GEVENT_LOOP=libuv GEVENTTEST_COVERAGE=1 make alltest
${PYTHON} scripts/travis.py fold_end libuv
${PYTHON} scripts/travis.py fold_start libev "Testing libev CFFI backend"
@${PYTHON} scripts/travis.py fold_end libuv
@${PYTHON} scripts/travis.py fold_start libev "Testing libev CFFI backend"
GEVENT_LOOP=libev-cffi make alltest
${PYTHON} scripts/travis.py fold_end libev
@${PYTHON} scripts/travis.py fold_end libev
leaktest: test_prelim
${PYTHON} scripts/travis.py fold_start leaktest "Running leak tests"
@${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
${PYTHON} scripts/travis.py fold_end leaktest
@${PYTHON} scripts/travis.py fold_end leaktest
bench:
${PYTHON} src/greentest/bench_sendall.py
......@@ -197,7 +197,13 @@ test-pypy3: $(PYPY3)
PYTHON=$(PYPY3) PATH=$(BUILD_RUNTIMES)/versions/pypy3.5_5101/bin:$(PATH) make develop basictest
test-py27-noembed: $(PY27)
@${PYTHON} scripts/travis.py fold_start conf_libev "Configuring libev"
cd deps/libev && ./configure --disable-dependency-tracking && make
@${PYTHON} scripts/travis.py fold_end conf_libev
@${PYTHON} scripts/travis.py fold_start conf_cares "Configuring cares"
cd deps/c-ares && ./configure --disable-dependency-tracking && make
@${PYTHON} scripts/travis.py fold_end conf_cares
@${PYTHON} scripts/travis.py fold_start conf_libuv "Configuring libuv"
cd deps/libuv && ./autogen.sh && ./configure --disable-static && make
@${PYTHON} scripts/travis.py fold_end conf_libuv
CPPFLAGS="-Ideps/libev -Ideps/c-ares -Ideps/libuv/include" LDFLAGS="-Ldeps/libev/.libs -Ldeps/c-ares/.libs -Ldeps/libuv/.libs" LD_LIBRARY_PATH="$(PWD)/deps/libev/.libs:$(PWD)/deps/c-ares/.libs:$(PWD)/deps/libuv/.libs" EMBED=0 GEVENT_LOOP=libev-cext PYTHON=python2.7.14 PATH=$(BUILD_RUNTIMES)/versions/python2.7.14/bin:$(PATH) make develop basictest
......@@ -101,8 +101,6 @@ 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
......
......@@ -95,7 +95,9 @@ class TestCaseMetaClass(type):
if sysinfo.RUN_LEAKCHECKS and timeout is not None:
timeout *= 6
check_totalrefcount = _get_class_attr(classDict, bases, 'check_totalrefcount', True)
error_fatal = _get_class_attr(classDict, bases, 'error_fatal', True)
uses_handle_error = _get_class_attr(classDict, bases, 'uses_handle_error', True)
# Python 3: must copy, we mutate the classDict. Interestingly enough,
# it doesn't actually error out, but under 3.6 we wind up wrapping
# and re-wrapping the same items over and over and over.
......@@ -108,7 +110,8 @@ class TestCaseMetaClass(type):
error_fatal = getattr(value, 'error_fatal', error_fatal)
if error_fatal:
value = errorhandler.wrap_error_fatal(value)
value = errorhandler.wrap_restore_handle_error(value)
if uses_handle_error:
value = errorhandler.wrap_restore_handle_error(value)
if check_totalrefcount and sysinfo.RUN_LEAKCHECKS:
value = leakcheck.wrap_refcount(value)
classDict[key] = value
......@@ -122,6 +125,7 @@ class TestCase(TestCaseMetaClass("NewBase", (TimeAssertMixin, BaseTestCase,), {}
switch_expected = 'default'
error_fatal = True
uses_handle_error = True
close_on_teardown = ()
def run(self, *args, **kwargs):
......
......@@ -105,9 +105,10 @@ class TestTimers(greentest.TestCase):
gevent.sleep(0.02)
gevent.spawn(func)
assert lst == [1], lst
gevent.sleep(0.03)
assert lst == [], lst
self.assertEqual(lst, [1])
gevent.sleep(0.1)
self.assertEqual(lst, [])
def test_spawn_is_not_cancelled(self):
lst = [1]
......@@ -116,8 +117,8 @@ class TestTimers(greentest.TestCase):
gevent.spawn(lst.pop)
# exiting immediately, but self.lst.pop must be called
gevent.spawn(func)
gevent.sleep(0.01)
assert lst == [], lst
gevent.sleep(0.1)
self.assertEqual(lst, [])
if __name__ == '__main__':
......
......@@ -9,11 +9,12 @@ from greentest.sysinfo import CFFI_BACKEND
class Test(TestCase):
__timeout__ = LARGE_TIMEOUT
repeat = 0
def setUp(self):
self.called = []
self.loop = config.loop(default=True)
self.loop = config.loop(default=False)
self.timer = self.loop.timer(0.001, repeat=self.repeat)
def cleanup(self):
......@@ -74,6 +75,8 @@ class TestAgain(Test):
self.assertEqual(x.args, (x,))
# XXX: On libev, this takes 1 second. On libuv,
# it takes the expected time.
self.loop.run()
self.assertEqual(self.called, [1])
......
......@@ -6,11 +6,13 @@ from gevent.event import Event, AsyncResult
import greentest
from greentest.skipping import skipUnderCoverage
from greentest.six import xrange
from greentest.timing import AbstractGenericGetTestCase
from greentest.timing import AbstractGenericWaitTestCase
DELAY = 0.01
class TestEventWait(greentest.GenericWaitTestCase):
class TestEventWait(AbstractGenericWaitTestCase):
def wait(self, timeout):
Event().wait(timeout=timeout)
......@@ -19,7 +21,7 @@ class TestEventWait(greentest.GenericWaitTestCase):
str(Event())
class TestWaitEvent(greentest.GenericWaitTestCase):
class TestWaitEvent(AbstractGenericWaitTestCase):
def wait(self, timeout):
gevent.wait([Event()], timeout=timeout)
......@@ -58,19 +60,19 @@ class TestWaitEvent(greentest.GenericWaitTestCase):
gevent.spawn(waiter).join()
class TestAsyncResultWait(greentest.GenericWaitTestCase):
class TestAsyncResultWait(AbstractGenericWaitTestCase):
def wait(self, timeout):
AsyncResult().wait(timeout=timeout)
class TestWaitAsyncResult(greentest.GenericWaitTestCase):
class TestWaitAsyncResult(AbstractGenericWaitTestCase):
def wait(self, timeout):
gevent.wait([AsyncResult()], timeout=timeout)
class TestAsyncResultGet(greentest.GenericGetTestCase):
class TestAsyncResultGet(AbstractGenericGetTestCase):
def wait(self, timeout):
AsyncResult().get(timeout=timeout)
......@@ -232,5 +234,8 @@ class TestWait_count2(TestWait):
count = 2
del AbstractGenericGetTestCase
del AbstractGenericWaitTestCase
if __name__ == '__main__':
greentest.main()
This diff is collapsed.
......@@ -20,6 +20,7 @@
# THE SOFTWARE.
import greentest
import greentest.timing
import time
import re
import gevent
......@@ -71,7 +72,7 @@ class TestExceptionInMainloop(greentest.TestCase):
class TestSleep(greentest.GenericWaitTestCase):
class TestSleep(greentest.timing.AbstractGenericWaitTestCase):
def wait(self, timeout):
gevent.sleep(timeout)
......@@ -80,7 +81,7 @@ class TestSleep(greentest.GenericWaitTestCase):
gevent.sleep(0)
class TestWaiterGet(greentest.GenericWaitTestCase):
class TestWaiterGet(greentest.timing.AbstractGenericWaitTestCase):
def setUp(self):
super(TestWaiterGet, self).setUp()
......
from time import time
import gevent
from gevent import pool
import gevent.pool
from gevent.event import Event
from gevent.queue import Queue
from gevent.timeout import Timeout
import greentest
import greentest.timing
import random
from greentest import ExpectedException
from greentest import six
......@@ -13,12 +14,12 @@ import unittest
class TestCoroutinePool(unittest.TestCase):
klass = pool.Pool
klass = gevent.pool.Pool
def test_apply_async(self):
done = Event()
def some_work(x):
def some_work(_):
done.set()
pool = self.klass(2)
......@@ -125,18 +126,18 @@ class TestCoroutinePool(unittest.TestCase):
pool.join()
def crash(*args, **kw):
def crash(*_args, **_kw):
raise RuntimeError("Whoa")
class FakeFile(object):
def write(*args):
def write(self, *_args):
raise RuntimeError('Whaaa')
class PoolBasicTests(greentest.TestCase):
klass = pool.Pool
klass = gevent.pool.Pool
def test_execute_async(self):
p = self.klass(size=2)
......@@ -208,7 +209,7 @@ class PoolBasicTests(greentest.TestCase):
second = gevent.spawn(gevent.sleep, 1000)
try:
p.add(first)
with self.assertRaises(pool.PoolFull):
with self.assertRaises(gevent.pool.PoolFull):
p.add(second, blocking=False)
finally:
second.kill()
......@@ -223,7 +224,7 @@ class PoolBasicTests(greentest.TestCase):
second = gevent.spawn(gevent.sleep, 1000)
try:
p.add(first)
with self.assertRaises(pool.PoolFull):
with self.assertRaises(gevent.pool.PoolFull):
p.add(second, timeout=0.100)
finally:
second.kill()
......@@ -238,7 +239,7 @@ class PoolBasicTests(greentest.TestCase):
second = gevent.Greenlet(gevent.sleep, 1000)
try:
p.add(first)
with self.assertRaises(pool.PoolFull):
with self.assertRaises(gevent.pool.PoolFull):
p.start(second, timeout=0.100)
finally:
second.kill()
......@@ -304,13 +305,13 @@ if greentest.PYPY and greentest.WIN:
elif greentest.RUNNING_ON_CI or greentest.EXPECT_POOR_TIMER_RESOLUTION:
LARGE_RANGE = 100
class TestPool(greentest.TestCase):
class TestPool(greentest.TestCase): # pylint:disable=too-many-public-methods
__timeout__ = greentest.LARGE_TIMEOUT
size = 1
def setUp(self):
greentest.TestCase.setUp(self)
self.pool = pool.Pool(self.size)
self.pool = gevent.pool.Pool(self.size)
def cleanup(self):
self.pool.join()
......@@ -438,17 +439,11 @@ class TestPool(greentest.TestCase):
running = [0]
def short_running_func(i, j):
def short_running_func(i, _j):
running[0] += 1
return i
# Send two iterables to make sure varargs and kwargs are handled
# correctly
for meth in self.pool.imap_unordered, self.pool.imap:
running[0] = 0
mapping = meth(short_running_func, iterable, iterable,
maxsize=1)
def make_reader(mapping):
# Simulate a long running reader. No matter how many workers
# we have, we will never have a queue more than size 1
def reader():
......@@ -459,7 +454,16 @@ class TestPool(greentest.TestCase):
gevent.sleep(0.01)
self.assertTrue(len(mapping.queue) <= 2, len(mapping.queue))
return result
return reader
# Send two iterables to make sure varargs and kwargs are handled
# correctly
for meth in self.pool.imap_unordered, self.pool.imap:
running[0] = 0
mapping = meth(short_running_func, iterable, iterable,
maxsize=1)
reader = make_reader(mapping)
l = reader()
self.assertEqual(sorted(l), iterable)
......@@ -484,16 +488,16 @@ class TestPool0(greentest.TestCase):
size = 0
def test_wait_full(self):
p = pool.Pool(size=0)
p = gevent.pool.Pool(size=0)
self.assertEqual(0, p.free_count())
self.assertTrue(p.full())
self.assertEqual(0, p.wait_available(timeout=0.01))
class TestJoinSleep(greentest.GenericWaitTestCase):
class TestJoinSleep(greentest.timing.AbstractGenericWaitTestCase):
def wait(self, timeout):
p = pool.Pool()
p = gevent.pool.Pool()
g = p.spawn(gevent.sleep, 10)
try:
p.join(timeout=timeout)
......@@ -501,10 +505,10 @@ class TestJoinSleep(greentest.GenericWaitTestCase):
g.kill()
class TestJoinSleep_raise_error(greentest.GenericWaitTestCase):
class TestJoinSleep_raise_error(greentest.timing.AbstractGenericWaitTestCase):
def wait(self, timeout):
p = pool.Pool()
p = gevent.pool.Pool()
g = p.spawn(gevent.sleep, 10)
try:
p.join(timeout=timeout, raise_error=True)
......@@ -516,7 +520,7 @@ class TestJoinEmpty(greentest.TestCase):
switch_expected = False
def test(self):
p = pool.Pool()
p = gevent.pool.Pool()
res = p.join()
self.assertTrue(res, "empty should return true")
......@@ -525,7 +529,7 @@ class TestSpawn(greentest.TestCase):
switch_expected = True
def test(self):
p = pool.Pool(1)
p = gevent.pool.Pool(1)
self.assertEqual(len(p), 0)
p.spawn(gevent.sleep, 0.1)
self.assertEqual(len(p), 1)
......@@ -535,7 +539,7 @@ class TestSpawn(greentest.TestCase):
self.assertEqual(len(p), 0)
def testSpawnAndWait(self):
p = pool.Pool(1)
p = gevent.pool.Pool(1)
self.assertEqual(len(p), 0)
p.spawn(gevent.sleep, 0.1)
self.assertEqual(len(p), 1)
......@@ -555,12 +559,12 @@ class TestErrorInIterator(greentest.TestCase):
error_fatal = False
def test(self):
p = pool.Pool(3)
p = gevent.pool.Pool(3)
self.assertRaises(ExpectedException, p.map, lambda x: None, error_iter())
gevent.sleep(0.001)
def test_unordered(self):
p = pool.Pool(3)
p = gevent.pool.Pool(3)
def unordered():
return list(p.imap_unordered(lambda x: None, error_iter()))
......@@ -577,11 +581,11 @@ class TestErrorInHandler(greentest.TestCase):
error_fatal = False
def test_map(self):
p = pool.Pool(3)
p = gevent.pool.Pool(3)
self.assertRaises(ZeroDivisionError, p.map, divide_by, [1, 0, 2])
def test_imap(self):
p = pool.Pool(1)
p = gevent.pool.Pool(1)
it = p.imap(divide_by, [1, 0, 2])
self.assertEqual(next(it), 1.0)
self.assertRaises(ZeroDivisionError, next, it)
......@@ -589,7 +593,7 @@ class TestErrorInHandler(greentest.TestCase):
self.assertRaises(StopIteration, next, it)
def test_imap_unordered(self):
p = pool.Pool(1)
p = gevent.pool.Pool(1)
it = p.imap_unordered(divide_by, [1, 0, 2])
self.assertEqual(next(it), 1.0)
self.assertRaises(ZeroDivisionError, next, it)
......
import greentest
from greentest import TestCase, main, GenericGetTestCase
from greentest import TestCase, main
import gevent
from gevent.hub import get_hub, LoopExit
from gevent import util
from gevent import queue
from gevent.queue import Empty, Full
from gevent.event import AsyncResult
from greentest.timing import AbstractGenericGetTestCase
# pylint:disable=too-many-ancestors
class TestQueue(TestCase):
......@@ -372,7 +374,7 @@ class TestJoinEmpty(TestCase):
q.join()
class TestGetInterrupt(GenericGetTestCase):
class TestGetInterrupt(AbstractGenericGetTestCase):
Timeout = Empty
......@@ -397,7 +399,7 @@ class TestGetInterruptChannel(TestGetInterrupt):
kind = queue.Channel
class TestPutInterrupt(GenericGetTestCase):
class TestPutInterrupt(AbstractGenericGetTestCase):
kind = queue.Queue
Timeout = Full
......@@ -430,7 +432,7 @@ class TestPutInterruptChannel(TestPutInterrupt):
return self.kind()
del GenericGetTestCase
del AbstractGenericGetTestCase
if __name__ == '__main__':
......
......@@ -5,86 +5,87 @@ import errno
from gevent import select, socket
import gevent.core
import greentest
import greentest.timing
import unittest
class TestSelect(greentest.GenericWaitTestCase):
class TestSelect(greentest.timing.AbstractGenericWaitTestCase):
def wait(self, timeout):
select.select([], [], [], timeout)
if sys.platform != 'win32':
class TestSelectRead(greentest.GenericWaitTestCase):
@greentest.skipOnWindows("Cant select on files")
class TestSelectRead(greentest.timing.AbstractGenericWaitTestCase):
def wait(self, timeout):
r, w = os.pipe()
def wait(self, timeout):
r, w = os.pipe()
try:
select.select([r], [], [], timeout)
finally:
os.close(r)
os.close(w)
# Issue #12367: http://www.freebsd.org/cgi/query-pr.cgi?pr=kern/155606
@unittest.skipIf(sys.platform.startswith('freebsd'),
'skip because of a FreeBSD bug: kern/155606')
def test_errno(self):
# Backported from test_select.py in 3.4
with open(__file__, 'rb') as fp:
fd = fp.fileno()
fp.close()
try:
select.select([r], [], [], timeout)
finally:
os.close(r)
os.close(w)
# Issue #12367: http://www.freebsd.org/cgi/query-pr.cgi?pr=kern/155606
@unittest.skipIf(sys.platform.startswith('freebsd'),
'skip because of a FreeBSD bug: kern/155606')
def test_errno(self):
# Backported from test_select.py in 3.4
with open(__file__, 'rb') as fp:
fd = fp.fileno()
fp.close()
try:
select.select([fd], [], [], 0)
except OSError as err:
# Python 3
self.assertEqual(err.errno, errno.EBADF)
except select.error as err: # pylint:disable=duplicate-except
# Python 2 (select.error is OSError on py3)
self.assertEqual(err.args[0], errno.EBADF)
else:
self.fail("exception not raised")
if hasattr(select, 'poll'):
class TestPollRead(greentest.GenericWaitTestCase):
def wait(self, timeout):
# On darwin, the read pipe is reported as writable
# immediately, for some reason. So we carefully register
# it only for read events (the default is read and write)
r, w = os.pipe()
try:
poll = select.poll()
poll.register(r, select.POLLIN)
poll.poll(timeout * 1000)
finally:
poll.unregister(r)
os.close(r)
os.close(w)
def test_unregister_never_registered(self):
# "Attempting to remove a file descriptor that was
# never registered causes a KeyError exception to be
# raised."
poll = select.poll()
self.assertRaises(KeyError, poll.unregister, 5)
@unittest.skipIf(hasattr(gevent.core, 'libuv'),
"Depending on whether the fileno is reused or not this either crashes or does nothing."
"libuv won't open a watcher for a closed file on linux.")
def test_poll_invalid(self):
with open(__file__, 'rb') as fp:
fd = fp.fileno()
poll = select.poll()
poll.register(fd, select.POLLIN)
# Close after registering; libuv refuses to even
# create a watcher if it would get EBADF (so this turns into
# a test of whether or not we successfully initted the watcher).
fp.close()
result = poll.poll(0)
self.assertEqual(result, [(fd, select.POLLNVAL)]) # pylint:disable=no-member
select.select([fd], [], [], 0)
except OSError as err:
# Python 3
self.assertEqual(err.errno, errno.EBADF)
except select.error as err: # pylint:disable=duplicate-except
# Python 2 (select.error is OSError on py3)
self.assertEqual(err.args[0], errno.EBADF)
else:
self.fail("exception not raised")
@unittest.skipUnless(hasattr(select, 'poll'), "Needs poll")
@greentest.skipOnWindows("Cant poll on files")
class TestPollRead(greentest.timing.AbstractGenericWaitTestCase):
def wait(self, timeout):
# On darwin, the read pipe is reported as writable
# immediately, for some reason. So we carefully register
# it only for read events (the default is read and write)
r, w = os.pipe()
try:
poll = select.poll()
poll.register(r, select.POLLIN)
poll.poll(timeout * 1000)
finally:
poll.unregister(r)
os.close(r)
os.close(w)
def test_unregister_never_registered(self):
# "Attempting to remove a file descriptor that was
# never registered causes a KeyError exception to be
# raised."
poll = select.poll()
self.assertRaises(KeyError, poll.unregister, 5)
@unittest.skipIf(hasattr(gevent.core, 'libuv'),
"Depending on whether the fileno is reused or not this either crashes or does nothing."
"libuv won't open a watcher for a closed file on linux.")
def test_poll_invalid(self):
with open(__file__, 'rb') as fp:
fd = fp.fileno()
poll = select.poll()
poll.register(fd, select.POLLIN)
# Close after registering; libuv refuses to even
# create a watcher if it would get EBADF (so this turns into
# a test of whether or not we successfully initted the watcher).
fp.close()
result = poll.poll(0)
self.assertEqual(result, [(fd, select.POLLNVAL)]) # pylint:disable=no-member
class TestSelectTypes(greentest.TestCase):
......
......@@ -27,6 +27,7 @@ from greentest.sysinfo import RESOLVER_NOT_SYSTEM
from greentest.sysinfo import RESOLVER_DNSPYTHON
from greentest.sysinfo import RESOLVER_ARES
from greentest.sysinfo import PY2
import greentest.timing
assert gevent_socket.gaierror is socket.gaierror
......@@ -570,7 +571,7 @@ add(TestInternational, u'президент.рф', 'russian',
add(TestInternational, u'президент.рф'.encode('idna'), 'idna')
class TestInterrupted_gethostbyname(greentest.GenericWaitTestCase):
class TestInterrupted_gethostbyname(greentest.timing.AbstractGenericWaitTestCase):
# There are refs to a Waiter in the C code that don't go
# away yet; one gc may or may not do it.
......
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