You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
111 lines
3.2 KiB
Python
111 lines
3.2 KiB
Python
5 years ago
|
import sys
|
||
|
import gevent.testing as greentest
|
||
|
import gevent
|
||
|
from gevent.hub import get_hub
|
||
|
|
||
|
def raise_(ex):
|
||
|
raise ex
|
||
|
|
||
|
|
||
|
MSG = 'should be re-raised and caught'
|
||
|
|
||
|
|
||
|
class Test(greentest.TestCase):
|
||
|
x = None
|
||
|
error_fatal = False
|
||
|
|
||
|
def start(self, *args):
|
||
|
raise NotImplementedError
|
||
|
|
||
|
def setUp(self):
|
||
|
self.x = None
|
||
|
|
||
|
def test_sys_exit(self):
|
||
|
self.start(sys.exit, MSG)
|
||
|
|
||
|
try:
|
||
|
gevent.sleep(0.001)
|
||
|
except SystemExit as ex:
|
||
|
assert str(ex) == MSG, repr(str(ex))
|
||
|
else:
|
||
|
raise AssertionError('must raise SystemExit')
|
||
|
|
||
|
def test_keyboard_interrupt(self):
|
||
|
self.start(raise_, KeyboardInterrupt)
|
||
|
|
||
|
try:
|
||
|
gevent.sleep(0.001)
|
||
|
except KeyboardInterrupt:
|
||
|
pass
|
||
|
else:
|
||
|
raise AssertionError('must raise KeyboardInterrupt')
|
||
|
|
||
|
def test_keyboard_interrupt_stderr_patched(self):
|
||
|
# XXX: This one non-top-level call prevents us from being
|
||
|
# run in a process with other tests.
|
||
|
from gevent import monkey
|
||
|
monkey.patch_sys(stdin=False, stdout=False, stderr=True)
|
||
|
try:
|
||
|
try:
|
||
|
self.start(raise_, KeyboardInterrupt)
|
||
|
while True:
|
||
|
gevent.sleep(0.1)
|
||
|
except KeyboardInterrupt:
|
||
|
pass # expected
|
||
|
finally:
|
||
|
sys.stderr = monkey.get_original('sys', 'stderr')
|
||
|
|
||
|
def test_system_error(self):
|
||
|
self.start(raise_, SystemError(MSG))
|
||
|
|
||
|
with self.assertRaisesRegex(SystemError,
|
||
|
MSG):
|
||
|
gevent.sleep(0.002)
|
||
|
|
||
|
def test_exception(self):
|
||
|
self.start(raise_, Exception('regular exception must not kill the program'))
|
||
|
gevent.sleep(0.001)
|
||
|
|
||
|
|
||
|
class TestCallback(Test):
|
||
|
|
||
|
def tearDown(self):
|
||
|
if self.x is not None:
|
||
|
# libuv: See the notes in libuv/loop.py:loop._start_callback_timer
|
||
|
# If that's broken, test_exception can fail sporadically.
|
||
|
# If the issue is the same, then adding `gevent.sleep(0)` here
|
||
|
# will solve it. There's also a race condition for the first loop,
|
||
|
# so we sleep twice.
|
||
|
assert not self.x.pending, self.x
|
||
|
|
||
|
def start(self, *args):
|
||
|
self.x = get_hub().loop.run_callback(*args)
|
||
|
|
||
|
if greentest.LIBUV:
|
||
|
def test_exception(self):
|
||
|
# This call will enter the loop for the very first time (if we're running
|
||
|
# standalone). On libuv, where timers run first, that means that depending on the
|
||
|
# amount of time that elapses between the call to uv_timer_start and uv_run,
|
||
|
# this timer might fire before our check or prepare watchers, and hence callbacks,
|
||
|
# run.
|
||
|
# We make this call now so that the call in the super class is guaranteed to be
|
||
|
# somewhere in the loop and not subject to that race condition.
|
||
|
gevent.sleep(0.001)
|
||
|
super(TestCallback, self).test_exception()
|
||
|
|
||
|
class TestSpawn(Test):
|
||
|
|
||
|
def tearDown(self):
|
||
|
gevent.sleep(0.0001)
|
||
|
if self.x is not None:
|
||
|
assert self.x.dead, self.x
|
||
|
|
||
|
def start(self, *args):
|
||
|
self.x = gevent.spawn(*args)
|
||
|
|
||
|
|
||
|
del Test
|
||
|
|
||
|
if __name__ == '__main__':
|
||
|
greentest.main()
|