Development of an internal social media platform with personalised dashboards for students
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.

test_mixins.py 7.9KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239
  1. from __future__ import absolute_import, unicode_literals
  2. import socket
  3. from kombu.mixins import ConsumerMixin
  4. from .case import Case, Mock, ContextMock, patch
  5. def Message(body, content_type='text/plain', content_encoding='utf-8'):
  6. m = Mock(name='Message')
  7. m.body = body
  8. m.content_type = content_type
  9. m.content_encoding = content_encoding
  10. return m
  11. class Cons(ConsumerMixin):
  12. def __init__(self, consumers):
  13. self.calls = Mock(name='ConsumerMixin')
  14. self.calls.get_consumers.return_value = consumers
  15. self.get_consumers = self.calls.get_consumers
  16. self.on_connection_revived = self.calls.on_connection_revived
  17. self.on_consume_ready = self.calls.on_consume_ready
  18. self.on_consume_end = self.calls.on_consume_end
  19. self.on_iteration = self.calls.on_iteration
  20. self.on_decode_error = self.calls.on_decode_error
  21. self.on_connection_error = self.calls.on_connection_error
  22. self.extra_context = ContextMock(name='extra_context')
  23. self.extra_context.return_value = self.extra_context
  24. class test_ConsumerMixin(Case):
  25. def _context(self):
  26. Acons = ContextMock(name='consumerA')
  27. Bcons = ContextMock(name='consumerB')
  28. c = Cons([Acons, Bcons])
  29. _conn = c.connection = ContextMock(name='connection')
  30. est = c.establish_connection = Mock(name='est_connection')
  31. est.return_value = _conn
  32. return c, Acons, Bcons
  33. def test_consume(self):
  34. c, Acons, Bcons = self._context()
  35. c.should_stop = False
  36. it = c.consume(no_ack=True)
  37. next(it)
  38. Acons.__enter__.assert_called_with()
  39. Bcons.__enter__.assert_called_with()
  40. c.extra_context.__enter__.assert_called_with()
  41. self.assertTrue(c.on_consume_ready.called)
  42. c.on_iteration.assert_called_with()
  43. c.connection.drain_events.assert_called_with(timeout=1)
  44. next(it)
  45. next(it)
  46. next(it)
  47. c.should_stop = True
  48. with self.assertRaises(StopIteration):
  49. next(it)
  50. def test_consume_drain_raises_socket_error(self):
  51. c, Acons, Bcons = self._context()
  52. c.should_stop = False
  53. it = c.consume(no_ack=True)
  54. c.connection.drain_events.side_effect = socket.error
  55. with self.assertRaises(socket.error):
  56. next(it)
  57. def se2(*args, **kwargs):
  58. c.should_stop = True
  59. raise socket.error()
  60. c.connection.drain_events.side_effect = se2
  61. it = c.consume(no_ack=True)
  62. with self.assertRaises(StopIteration):
  63. next(it)
  64. def test_consume_drain_raises_socket_timeout(self):
  65. c, Acons, Bcons = self._context()
  66. c.should_stop = False
  67. it = c.consume(no_ack=True, timeout=1)
  68. def se(*args, **kwargs):
  69. c.should_stop = True
  70. raise socket.timeout()
  71. c.connection.drain_events.side_effect = se
  72. with self.assertRaises(socket.error):
  73. next(it)
  74. def test_Consumer_context(self):
  75. c, Acons, Bcons = self._context()
  76. with c.Consumer() as (conn, channel, consumer):
  77. self.assertIs(conn, c.connection)
  78. self.assertIs(channel, conn.default_channel)
  79. c.on_connection_revived.assert_called_with()
  80. self.assertTrue(c.get_consumers.called)
  81. cls = c.get_consumers.call_args[0][0]
  82. subcons = cls()
  83. self.assertIs(subcons.on_decode_error, c.on_decode_error)
  84. self.assertIs(subcons.channel, conn.default_channel)
  85. Acons.__enter__.assert_called_with()
  86. Bcons.__enter__.assert_called_with()
  87. c.on_consume_end.assert_called_with(conn, channel)
  88. class test_ConsumerMixin_interface(Case):
  89. def setUp(self):
  90. self.c = ConsumerMixin()
  91. def test_get_consumers(self):
  92. with self.assertRaises(NotImplementedError):
  93. self.c.get_consumers(Mock(), Mock())
  94. def test_on_connection_revived(self):
  95. self.assertIsNone(self.c.on_connection_revived())
  96. def test_on_consume_ready(self):
  97. self.assertIsNone(self.c.on_consume_ready(
  98. Mock(), Mock(), [],
  99. ))
  100. def test_on_consume_end(self):
  101. self.assertIsNone(self.c.on_consume_end(Mock(), Mock()))
  102. def test_on_iteration(self):
  103. self.assertIsNone(self.c.on_iteration())
  104. def test_on_decode_error(self):
  105. message = Message('foo')
  106. with patch('kombu.mixins.error') as error:
  107. self.c.on_decode_error(message, KeyError('foo'))
  108. self.assertTrue(error.called)
  109. message.ack.assert_called_with()
  110. def test_on_connection_error(self):
  111. with patch('kombu.mixins.warn') as warn:
  112. self.c.on_connection_error(KeyError('foo'), 3)
  113. self.assertTrue(warn.called)
  114. def test_extra_context(self):
  115. with self.c.extra_context(Mock(), Mock()):
  116. pass
  117. def test_restart_limit(self):
  118. self.assertTrue(self.c.restart_limit)
  119. def test_connection_errors(self):
  120. conn = Mock(name='connection')
  121. self.c.connection = conn
  122. conn.connection_errors = (KeyError, )
  123. self.assertTupleEqual(self.c.connection_errors, conn.connection_errors)
  124. conn.channel_errors = (ValueError, )
  125. self.assertTupleEqual(self.c.channel_errors, conn.channel_errors)
  126. def test__consume_from(self):
  127. a = ContextMock(name='A')
  128. b = ContextMock(name='B')
  129. a.__enter__ = Mock(name='A.__enter__')
  130. b.__enter__ = Mock(name='B.__enter__')
  131. with self.c._consume_from(a, b):
  132. pass
  133. a.__enter__.assert_called_with()
  134. b.__enter__.assert_called_with()
  135. def test_establish_connection(self):
  136. conn = ContextMock(name='connection')
  137. conn.clone.return_value = conn
  138. self.c.connection = conn
  139. self.c.connect_max_retries = 3
  140. with self.c.establish_connection() as conn:
  141. self.assertTrue(conn)
  142. conn.ensure_connection.assert_called_with(
  143. self.c.on_connection_error, 3,
  144. )
  145. def test_maybe_conn_error(self):
  146. conn = ContextMock(name='connection')
  147. conn.connection_errors = (KeyError, )
  148. conn.channel_errors = ()
  149. self.c.connection = conn
  150. def raises():
  151. raise KeyError('foo')
  152. self.c.maybe_conn_error(raises)
  153. def test_run(self):
  154. conn = ContextMock(name='connection')
  155. self.c.connection = conn
  156. conn.connection_errors = (KeyError, )
  157. conn.channel_errors = ()
  158. consume = self.c.consume = Mock(name='c.consume')
  159. def se(*args, **kwargs):
  160. self.c.should_stop = True
  161. return [1]
  162. self.c.should_stop = False
  163. consume.side_effect = se
  164. self.c.run()
  165. def test_run_restart_rate_limited(self):
  166. conn = ContextMock(name='connection')
  167. self.c.connection = conn
  168. conn.connection_errors = (KeyError, )
  169. conn.channel_errors = ()
  170. consume = self.c.consume = Mock(name='c.consume')
  171. with patch('kombu.mixins.sleep') as sleep:
  172. counter = [0]
  173. def se(*args, **kwargs):
  174. if counter[0] >= 1:
  175. self.c.should_stop = True
  176. counter[0] += 1
  177. return counter
  178. self.c.should_stop = False
  179. consume.side_effect = se
  180. self.c.run()
  181. self.assertTrue(sleep.called)
  182. def test_run_raises(self):
  183. conn = ContextMock(name='connection')
  184. self.c.connection = conn
  185. conn.connection_errors = (KeyError, )
  186. conn.channel_errors = ()
  187. consume = self.c.consume = Mock(name='c.consume')
  188. with patch('kombu.mixins.warn') as warn:
  189. def se_raises(*args, **kwargs):
  190. self.c.should_stop = True
  191. raise KeyError('foo')
  192. self.c.should_stop = False
  193. consume.side_effect = se_raises
  194. self.c.run()
  195. self.assertTrue(warn.called)