test_hub.py 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269
  1. from __future__ import absolute_import
  2. from __future__ import with_statement
  3. from celery.worker.hub import (
  4. DummyLock,
  5. BoundedSemaphore,
  6. Hub,
  7. )
  8. from mock import Mock, call, patch
  9. from celery.tests.utils import Case
  10. class File(object):
  11. def __init__(self, fd):
  12. self.fd = fd
  13. def fileno(self):
  14. return self.fd
  15. def __eq__(self, other):
  16. if isinstance(other, File):
  17. return self.fd == other.fd
  18. return NotImplemented
  19. class test_DummyLock(Case):
  20. def test_context(self):
  21. mutex = DummyLock()
  22. with mutex:
  23. pass
  24. class test_BoundedSemaphore(Case):
  25. def test_acquire_release(self):
  26. x = BoundedSemaphore(2)
  27. c1 = Mock()
  28. x.acquire(c1, 1)
  29. self.assertEqual(x.value, 1)
  30. c1.assert_called_with(1)
  31. c2 = Mock()
  32. x.acquire(c2, 2)
  33. self.assertEqual(x.value, 0)
  34. c2.assert_called_with(2)
  35. c3 = Mock()
  36. x.acquire(c3, 3)
  37. self.assertEqual(x.value, 0)
  38. self.assertFalse(c3.called)
  39. x.release()
  40. self.assertEqual(x.value, 1)
  41. c3.assert_called_with(3)
  42. def test_bounded(self):
  43. x = BoundedSemaphore(2)
  44. for i in xrange(100):
  45. x.release()
  46. self.assertEqual(x.value, 2)
  47. def test_grow_shrink(self):
  48. x = BoundedSemaphore(1)
  49. self.assertEqual(x.initial_value, 1)
  50. cb1 = Mock()
  51. x.acquire(cb1, 1)
  52. cb1.assert_called_with(1)
  53. self.assertEqual(x.value, 0)
  54. cb2 = Mock()
  55. x.acquire(cb2, 2)
  56. self.assertFalse(cb2.called)
  57. self.assertEqual(x.value, 0)
  58. cb3 = Mock()
  59. x.acquire(cb3, 3)
  60. self.assertFalse(cb3.called)
  61. x.grow(2)
  62. cb2.assert_called_with(2)
  63. cb3.assert_called_with(3)
  64. self.assertEqual(x.value, 3)
  65. self.assertEqual(x.initial_value, 3)
  66. self.assertFalse(x._waiting)
  67. x.grow(3)
  68. for i in xrange(x.initial_value):
  69. self.assertTrue(x.acquire(Mock()))
  70. self.assertFalse(x.acquire(Mock()))
  71. x.clear()
  72. x.shrink(3)
  73. for i in xrange(x.initial_value):
  74. self.assertTrue(x.acquire(Mock()))
  75. self.assertFalse(x.acquire(Mock()))
  76. self.assertEqual(x.value, 0)
  77. for i in xrange(100):
  78. x.release()
  79. self.assertEqual(x.value, x.initial_value)
  80. def test_clear(self):
  81. x = BoundedSemaphore(10)
  82. for i in xrange(11):
  83. x.acquire(Mock())
  84. self.assertTrue(x._waiting)
  85. self.assertEqual(x.value, 0)
  86. x.clear()
  87. self.assertFalse(x._waiting)
  88. self.assertEqual(x.value, x.initial_value)
  89. class test_Hub(Case):
  90. @patch('kombu.utils.eventio.poll')
  91. def test_start_stop(self, poll):
  92. hub = Hub()
  93. hub.start()
  94. poll.assert_called_with()
  95. hub.stop()
  96. hub.poller.close.assert_called_with()
  97. def test_init(self):
  98. hub = Hub()
  99. cb1 = Mock()
  100. cb2 = Mock()
  101. hub.on_init.extend([cb1, cb2])
  102. hub.init()
  103. cb1.assert_called_with(hub)
  104. cb2.assert_called_with(hub)
  105. def test_fire_timers(self):
  106. hub = Hub()
  107. hub.timer = Mock()
  108. hub.timer._queue = []
  109. self.assertEqual(hub.fire_timers(min_delay=42.324,
  110. max_delay=32.321), 32.321)
  111. hub.timer._queue = [1]
  112. hub.scheduler = Mock()
  113. hub.scheduler.next.return_value = 3.743, None
  114. self.assertEqual(hub.fire_timers(), 3.743)
  115. e1, e2, e3 = Mock(), Mock(), Mock()
  116. entries = [e1, e2, e3]
  117. reset = lambda: [m.reset() for m in [e1, e2, e3]]
  118. def se():
  119. if entries:
  120. return None, entries.pop()
  121. return 3.982, None
  122. hub.scheduler.next = Mock()
  123. hub.scheduler.next.side_effect = se
  124. self.assertEqual(hub.fire_timers(max_timers=10), 3.982)
  125. for E in [e3, e2, e1]:
  126. E.assert_called_with()
  127. reset()
  128. entries[:] = [Mock() for _ in xrange(11)]
  129. keep = list(entries)
  130. self.assertEqual(hub.fire_timers(max_timers=10, min_delay=1.13), 1.13)
  131. for E in reversed(keep[1:]):
  132. E.assert_called_with()
  133. reset()
  134. self.assertEqual(hub.fire_timers(max_timers=10), 3.982)
  135. keep[0].assert_called_with()
  136. def test_update_readers(self):
  137. hub = Hub()
  138. P = hub.poller = Mock()
  139. read_A = Mock()
  140. read_B = Mock()
  141. hub.update_readers({10: read_A, File(11): read_B})
  142. P.register.assert_has_calls([
  143. call(10, hub.READ | hub.ERR),
  144. call(File(11), hub.READ | hub.ERR),
  145. ], any_order=True)
  146. self.assertIs(hub.readers[10], read_A)
  147. self.assertIs(hub.readers[11], read_B)
  148. hub.remove(10)
  149. self.assertNotIn(10, hub.readers)
  150. hub.remove(File(11))
  151. self.assertNotIn(11, hub.readers)
  152. P.unregister.assert_has_calls([
  153. call(10), call(File(11)),
  154. ])
  155. def test_can_remove_unknown_fds(self):
  156. hub = Hub()
  157. hub.poller = Mock()
  158. hub.remove(30)
  159. hub.remove(File(301))
  160. def test_remove__unregister_raises(self):
  161. hub = Hub()
  162. hub.poller = Mock()
  163. hub.poller.unregister.side_effect = OSError()
  164. hub.remove(313)
  165. def test_update_writers(self):
  166. hub = Hub()
  167. P = hub.poller = Mock()
  168. write_A = Mock()
  169. write_B = Mock()
  170. hub.update_writers({20: write_A, File(21): write_B})
  171. P.register.assert_has_calls([
  172. call(20, hub.WRITE),
  173. call(File(21), hub.WRITE),
  174. ], any_order=True)
  175. self.assertIs(hub.writers[20], write_A)
  176. self.assertIs(hub.writers[21], write_B)
  177. hub.remove(20)
  178. self.assertNotIn(20, hub.writers)
  179. hub.remove(File(21))
  180. self.assertNotIn(21, hub.writers)
  181. P.unregister.assert_has_calls([
  182. call(20), call(File(21)),
  183. ])
  184. def test_enter__exit(self):
  185. hub = Hub()
  186. P = hub.poller = Mock()
  187. hub.init = Mock()
  188. on_close = Mock()
  189. hub.on_close.append(on_close)
  190. with hub:
  191. hub.init.assert_called_with()
  192. read_A = Mock()
  193. read_B = Mock()
  194. hub.update_readers({10: read_A, File(11): read_B})
  195. write_A = Mock()
  196. write_B = Mock()
  197. hub.update_writers({20: write_A, File(21): write_B})
  198. self.assertTrue(hub.readers)
  199. self.assertTrue(hub.writers)
  200. self.assertFalse(hub.readers)
  201. self.assertFalse(hub.writers)
  202. P.unregister.assert_has_calls([
  203. call(10), call(11), call(20), call(21),
  204. ], any_order=True)
  205. on_close.assert_called_with(hub)
  206. def test_scheduler_property(self):
  207. hub = Hub(timer=[1, 2, 3])
  208. self.assertEqual(list(hub.scheduler), [1, 2, 3])