171 lines
5.2 KiB
Python
171 lines
5.2 KiB
Python
from __future__ import with_statement
|
|
import unittest
|
|
import sys
|
|
from eventlet.coros import event, Job, JobGroup
|
|
from eventlet.api import spawn, sleep, GreenletExit, exc_after, timeout
|
|
|
|
DELAY= 0.01
|
|
|
|
class TestEvent(unittest.TestCase):
|
|
|
|
def test_send_exc(self):
|
|
log = []
|
|
e = event()
|
|
|
|
def waiter():
|
|
try:
|
|
result = e.wait()
|
|
log.append(('received', result))
|
|
except Exception, ex:
|
|
log.append(('catched', type(ex).__name__))
|
|
spawn(waiter)
|
|
sleep(0) # let waiter to block on e.wait()
|
|
e.send(exc=Exception())
|
|
sleep(0)
|
|
assert log == [('catched', 'Exception')], log
|
|
|
|
def test_send(self):
|
|
event1 = event()
|
|
event2 = event()
|
|
|
|
spawn(event1.send, 'hello event1')
|
|
exc_after(0, ValueError('interrupted'))
|
|
try:
|
|
result = event1.wait()
|
|
except ValueError:
|
|
with timeout(DELAY, None):
|
|
result = event2.wait()
|
|
raise AssertionError('Nobody sent anything to event2 yet it received %r' % (result, ))
|
|
|
|
class CommonJobTests:
|
|
|
|
def test_simple_return(self):
|
|
res = self.Job.spawn_new(lambda: 25).wait()
|
|
assert res==25, res
|
|
|
|
def test_exception(self):
|
|
try:
|
|
self.Job.spawn_new(sys.exit, 'bye').wait()
|
|
except SystemExit, ex:
|
|
assert ex.args == ('bye', )
|
|
else:
|
|
assert False, "Shouldn't get there"
|
|
|
|
def _test_kill(self, sync):
|
|
def func():
|
|
sleep(DELAY)
|
|
return 101
|
|
res = self.Job.spawn_new(func)
|
|
assert res
|
|
if sync:
|
|
res.kill()
|
|
else:
|
|
spawn(res.kill)
|
|
wait_result = res.wait()
|
|
assert not res, repr(res)
|
|
assert isinstance(wait_result, GreenletExit), repr(wait_result)
|
|
|
|
def test_kill_sync(self):
|
|
return self._test_kill(True)
|
|
|
|
def test_kill_async(self):
|
|
return self._test_kill(False)
|
|
|
|
def test_poll(self):
|
|
def func():
|
|
sleep(DELAY)
|
|
return 25
|
|
job = self.Job.spawn_new(func)
|
|
self.assertEqual(job.poll(), None)
|
|
assert job, repr(job)
|
|
self.assertEqual(job.wait(), 25)
|
|
self.assertEqual(job.poll(), 25)
|
|
assert not job, repr(job)
|
|
|
|
job = self.Job.spawn_new(func)
|
|
self.assertEqual(job.poll(5), 5)
|
|
assert job, repr(job)
|
|
self.assertEqual(job.wait(), 25)
|
|
self.assertEqual(job.poll(5), 25)
|
|
assert not job, repr(job)
|
|
|
|
def test_kill_after(self):
|
|
def func():
|
|
sleep(DELAY)
|
|
return 25
|
|
job = self.Job.spawn_new(func)
|
|
job.kill_after(DELAY/2)
|
|
result = job.wait()
|
|
assert isinstance(result, GreenletExit), repr(result)
|
|
|
|
job = self.Job.spawn_new(func)
|
|
job.kill_after(DELAY*2)
|
|
self.assertEqual(job.wait(), 25)
|
|
sleep(DELAY*2)
|
|
self.assertEqual(job.wait(), 25)
|
|
|
|
class TestJob(CommonJobTests, unittest.TestCase):
|
|
|
|
def setUp(self):
|
|
self.Job = Job
|
|
|
|
class TestJobGroup(CommonJobTests, unittest.TestCase):
|
|
|
|
def setUp(self):
|
|
self.Job = JobGroup()
|
|
|
|
def tearDown(self):
|
|
del self.Job
|
|
|
|
def check_raises_badint(self, wait):
|
|
try:
|
|
wait()
|
|
except ValueError, ex:
|
|
assert 'badint' in str(ex), str(ex)
|
|
else:
|
|
raise AssertionError('must raise ValueError')
|
|
|
|
def check_killed(self, wait, text=''):
|
|
result = wait()
|
|
assert isinstance(result, GreenletExit), repr(result)
|
|
assert str(result) == text, str(result)
|
|
|
|
def test_group_error(self):
|
|
x = self.Job.spawn_new(int, 'badint')
|
|
y = self.Job.spawn_new(sleep, DELAY)
|
|
self.check_killed(y.wait, 'Killed because of ValueError in the group')
|
|
self.check_raises_badint(x.wait)
|
|
z = self.Job.spawn_new(sleep, DELAY)
|
|
self.check_killed(z.wait, 'Killed because of ValueError in the group')
|
|
|
|
def test_wait_all(self):
|
|
x = self.Job.spawn_new(lambda : 1)
|
|
y = self.Job.spawn_new(lambda : 2)
|
|
z = self.Job.spawn_new(lambda : 3)
|
|
assert self.Job.wait_all() == [1, 2, 3], repr(self.Job.wait_all())
|
|
assert [x.wait(), y.wait(), z.wait()] == [1, 2, 3], [x.wait(), y.wait(), z.wait()]
|
|
|
|
def test_error_wait_all(self):
|
|
def x():
|
|
sleep(DELAY)
|
|
return 1
|
|
# x will be killed
|
|
x = self.Job.spawn_new(x)
|
|
# y will raise ValueError
|
|
y = self.Job.spawn_new(int, 'badint')
|
|
# z cannot be killed because it does not yield. it will finish successfully
|
|
z = self.Job.spawn_new(lambda : 3)
|
|
self.check_raises_badint(self.Job.wait_all)
|
|
self.check_killed(x.poll, 'Killed because of ValueError in the group')
|
|
self.check_killed(x.wait, 'Killed because of ValueError in the group')
|
|
assert z.wait() == 3, repr(z.wait())
|
|
self.check_raises_badint(y.wait)
|
|
|
|
# zz won't be even started, because there's already an error in the group
|
|
zz = self.Job.spawn_new(lambda : 4)
|
|
self.check_killed(x.poll, 'Killed because of ValueError in the group')
|
|
self.check_killed(x.wait, 'Killed because of ValueError in the group')
|
|
|
|
if __name__=='__main__':
|
|
unittest.main()
|