You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
158 lines
4.2 KiB
158 lines
4.2 KiB
5 years ago
|
from __future__ import print_function
|
||
|
from gevent import config
|
||
|
|
||
|
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):
|
||
|
__timeout__ = LARGE_TIMEOUT
|
||
|
|
||
|
repeat = 0
|
||
|
timer_duration = 0.001
|
||
|
|
||
|
def setUp(self):
|
||
|
super(Test, self).setUp()
|
||
|
self.called = []
|
||
|
self.loop = config.loop(default=False)
|
||
|
self.timer = self.loop.timer(self.timer_duration, repeat=self.repeat)
|
||
|
assert not self.loop.default
|
||
|
|
||
|
def cleanup(self):
|
||
|
# cleanup instead of tearDown to cooperate well with
|
||
|
# leakcheck.py
|
||
|
self.timer.close()
|
||
|
# cycle the loop so libuv close callbacks fire
|
||
|
self.loop.run()
|
||
|
self.loop.destroy()
|
||
|
self.loop = None
|
||
|
self.timer = None
|
||
|
|
||
|
def f(self, x=None):
|
||
|
self.called.append(1)
|
||
|
if x is not None:
|
||
|
x.stop()
|
||
|
|
||
|
def assertTimerInKeepalive(self):
|
||
|
if CFFI_BACKEND:
|
||
|
self.assertIn(self.timer, self.loop._keepaliveset)
|
||
|
|
||
|
def assertTimerNotInKeepalive(self):
|
||
|
if CFFI_BACKEND:
|
||
|
self.assertNotIn(self.timer, self.loop._keepaliveset)
|
||
|
|
||
|
def test_main(self):
|
||
|
loop = self.loop
|
||
|
x = self.timer
|
||
|
x.start(self.f)
|
||
|
self.assertTimerInKeepalive()
|
||
|
self.assertTrue(x.active, x)
|
||
|
|
||
|
with self.assertRaises((AttributeError, ValueError)):
|
||
|
x.priority = 1
|
||
|
|
||
|
loop.run()
|
||
|
self.assertEqual(x.pending, 0)
|
||
|
self.assertEqual(self.called, [1])
|
||
|
self.assertIsNone(x.callback)
|
||
|
self.assertIsNone(x.args)
|
||
|
|
||
|
if x.priority is not None:
|
||
|
self.assertEqual(x.priority, 0)
|
||
|
x.priority = 1
|
||
|
self.assertEqual(x.priority, 1)
|
||
|
|
||
|
x.stop()
|
||
|
self.assertTimerNotInKeepalive()
|
||
|
|
||
|
class TestAgain(Test):
|
||
|
repeat = 1
|
||
|
|
||
|
def test_main(self):
|
||
|
# Again works for a new timer
|
||
|
x = self.timer
|
||
|
x.again(self.f, x)
|
||
|
self.assertTimerInKeepalive()
|
||
|
|
||
|
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])
|
||
|
|
||
|
x.stop()
|
||
|
self.assertTimerNotInKeepalive()
|
||
|
|
||
|
|
||
|
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): # 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)
|
||
|
|
||
|
# https://github.com/gevent/gevent/pull/1194
|
||
|
from gevent._compat import perf_counter
|
||
|
|
||
|
import socket
|
||
|
s = socket.socket()
|
||
|
self._close_on_teardown(s)
|
||
|
fd = s.fileno()
|
||
|
|
||
|
ran_at_least_once = False
|
||
|
fired_at = []
|
||
|
|
||
|
def timer_counter():
|
||
|
fired_at.append(perf_counter())
|
||
|
|
||
|
loop = self.loop
|
||
|
|
||
|
timer_multiplier = 11
|
||
|
max_time = self.timer_duration * timer_multiplier
|
||
|
assert max_time < 0.3
|
||
|
|
||
|
for _ in range(150):
|
||
|
# in libuv, our signal timer fires every 300ms; depending on
|
||
|
# when this runs, we could artificially get a better
|
||
|
# resolution than we expect. Run it multiple times to be more sure.
|
||
|
io = loop.io(fd, 1)
|
||
|
io.start(lambda events=None: None)
|
||
|
|
||
|
|
||
|
now = perf_counter()
|
||
|
del fired_at[:]
|
||
|
timer = self.timer
|
||
|
timer.start(timer_counter)
|
||
|
|
||
|
loop.run(once=True)
|
||
|
|
||
|
io.stop()
|
||
|
io.close()
|
||
|
|
||
|
timer.stop()
|
||
|
|
||
|
if fired_at:
|
||
|
ran_at_least_once = True
|
||
|
self.assertEqual(1, len(fired_at))
|
||
|
self.assertTimeWithinRange(fired_at[0] - now,
|
||
|
0,
|
||
|
max_time)
|
||
|
|
||
|
|
||
|
if not greentest.RUNNING_ON_CI:
|
||
|
# Hmm, this always fires locally on mocOS but
|
||
|
# not an Travis?
|
||
|
self.assertTrue(ran_at_least_once)
|
||
|
|
||
|
|
||
|
if __name__ == '__main__':
|
||
|
greentest.main()
|