test_event_system.py 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302
  1. import unittest
  2. from cloudbridge.cloud.base.events import SimpleEventDispatcher
  3. from cloudbridge.cloud.interfaces.exceptions import HandlerException
  4. class EventSystemTestCase(unittest.TestCase):
  5. def test_emit_event_no_handlers(self):
  6. dispatcher = SimpleEventDispatcher()
  7. result = dispatcher.emit(self, "event.hello.world")
  8. self.assertIsNone(result, "Result should be none as there are no"
  9. "registered handlers")
  10. def test_emit_event_observing_handler(self):
  11. EVENT_NAME = "event.hello.world"
  12. callback_tracker = ['']
  13. def my_callback(**kwargs):
  14. self.assertDictEqual(kwargs,
  15. {'sender': self,
  16. 'event_name': EVENT_NAME})
  17. callback_tracker[0] += 'obs'
  18. return "hello"
  19. dispatcher = SimpleEventDispatcher()
  20. dispatcher.observe(EVENT_NAME, 1000, my_callback)
  21. result = dispatcher.emit(self, EVENT_NAME)
  22. self.assertEqual(
  23. callback_tracker[0], "obs", "callback should have been invoked"
  24. "once and contain value `obs` but tracker value is {0}".format(
  25. callback_tracker[0]))
  26. self.assertIsNone(result, "Result should be none as this is an"
  27. " observing handler")
  28. def test_emit_event_intercepting_handler(self):
  29. EVENT_NAME = "event.hello.world"
  30. callback_tracker = ['']
  31. def my_callback(**kwargs):
  32. self.assertDictEqual(kwargs,
  33. {'sender': self,
  34. 'event_name': EVENT_NAME,
  35. 'next_handler': None})
  36. callback_tracker[0] += "intcpt"
  37. return "world"
  38. dispatcher = SimpleEventDispatcher()
  39. dispatcher.intercept(EVENT_NAME, 1000, my_callback)
  40. result = dispatcher.emit(self, EVENT_NAME)
  41. self.assertEqual(
  42. callback_tracker[0], "intcpt", "callback should have been invoked"
  43. "once and contain value `intcpt` but tracker value is {0}".format(
  44. callback_tracker[0]))
  45. self.assertEqual(result, "world", "Result should be `world` as this"
  46. " is an intercepting handler")
  47. def test_emit_event_observe_precedes_intercept(self):
  48. EVENT_NAME = "event.hello.world"
  49. callback_tracker = ['']
  50. def my_callback_obs(**kwargs):
  51. self.assertDictEqual(kwargs,
  52. {'sender': self,
  53. 'event_name': EVENT_NAME})
  54. callback_tracker[0] += "obs_"
  55. return "hello"
  56. def my_callback_intcpt(**kwargs):
  57. self.assertDictEqual(kwargs,
  58. {'sender': self,
  59. 'event_name': EVENT_NAME,
  60. 'next_handler': None})
  61. callback_tracker[0] += "intcpt_"
  62. return "world"
  63. dispatcher = SimpleEventDispatcher()
  64. dispatcher.observe(EVENT_NAME, 1000, my_callback_obs)
  65. dispatcher.intercept(EVENT_NAME, 1001, my_callback_intcpt)
  66. result = dispatcher.emit(self, EVENT_NAME)
  67. self.assertEqual(
  68. callback_tracker[0], "obs_intcpt_", "callback was not invoked in "
  69. "expected order. Should have been obs_intcpt_ but is {0}".format(
  70. callback_tracker[0]))
  71. self.assertEqual(result, "world", "Result should be `world` as this"
  72. " is the return value of the intercepting handler")
  73. def test_emit_event_observe_follows_intercept(self):
  74. EVENT_NAME = "event.hello.world"
  75. callback_tracker = ['']
  76. def my_callback_intcpt(**kwargs):
  77. self.assertEqual(kwargs.get('sender'), self)
  78. self.assertEqual(kwargs.get('next_handler').priority, 1001)
  79. self.assertEqual(kwargs.get('next_handler').callback.__name__,
  80. "my_callback_obs")
  81. callback_tracker[0] += "intcpt_"
  82. # invoke next handler
  83. retval = kwargs.get('next_handler').invoke(**kwargs)
  84. self.assertIsNone(retval, "Return values of observable handlers"
  85. " should not be propagated.")
  86. return "world"
  87. def my_callback_obs(**kwargs):
  88. self.assertDictEqual(kwargs,
  89. {'sender': self,
  90. 'event_name': EVENT_NAME})
  91. callback_tracker[0] += "obs_"
  92. return "hello"
  93. dispatcher = SimpleEventDispatcher()
  94. # register priorities out of order to test that too
  95. dispatcher.observe(EVENT_NAME, 1001, my_callback_obs)
  96. dispatcher.intercept(EVENT_NAME, 1000, my_callback_intcpt)
  97. result = dispatcher.emit(self, EVENT_NAME)
  98. self.assertEqual(
  99. callback_tracker[0], "intcpt_obs_", "callback was not invoked in "
  100. "expected order. Should have been intcpt_obs_ but is {0}".format(
  101. callback_tracker[0]))
  102. self.assertEqual(result, "world", "Result should be `world` as this"
  103. " is the return value of the intercepting handler")
  104. def test_emit_event_intercept_follows_intercept(self):
  105. EVENT_NAME = "event.hello.world"
  106. callback_tracker = ['']
  107. def my_callback_intcpt1(**kwargs):
  108. self.assertEqual(kwargs.get('sender'), self)
  109. self.assertEqual(kwargs.get('next_handler').priority, 2020)
  110. self.assertEqual(kwargs.get('next_handler').callback.__name__,
  111. "my_callback_intcpt2")
  112. callback_tracker[0] += "intcpt1_"
  113. # invoke next handler but ignore return value
  114. return "hello" + kwargs.get('next_handler').invoke(**kwargs)
  115. def my_callback_intcpt2(**kwargs):
  116. self.assertDictEqual(kwargs,
  117. {'sender': self,
  118. 'event_name': EVENT_NAME,
  119. 'next_handler': None})
  120. callback_tracker[0] += "intcpt2_"
  121. return "world"
  122. dispatcher = SimpleEventDispatcher()
  123. dispatcher.intercept(EVENT_NAME, 2000, my_callback_intcpt1)
  124. dispatcher.intercept(EVENT_NAME, 2020, my_callback_intcpt2)
  125. result = dispatcher.emit(self, EVENT_NAME)
  126. self.assertEqual(
  127. callback_tracker[0], "intcpt1_intcpt2_", "callback was not invoked"
  128. " in expected order. Should have been intcpt1_intcpt2_ but is"
  129. " {0}".format(callback_tracker[0]))
  130. self.assertEqual(result, "helloworld", "Result should be `helloworld` "
  131. "as this is the expected return value from the chain")
  132. def test_subscribe_event_duplicate_priority(self):
  133. def my_callback(**kwargs):
  134. pass
  135. dispatcher = SimpleEventDispatcher()
  136. dispatcher.intercept("event.hello.world", 1000, my_callback)
  137. dispatcher.intercept("event.hello.world", 1000, my_callback)
  138. with self.assertRaises(HandlerException):
  139. dispatcher.emit(self, "event.hello.world")
  140. def test_subscribe_event_duplicate_wildcard_priority(self):
  141. def my_callback(**kwargs):
  142. pass
  143. dispatcher = SimpleEventDispatcher()
  144. dispatcher.intercept("event.hello.world", 1000, my_callback)
  145. dispatcher.intercept("event.hello.*", 1000, my_callback)
  146. with self.assertRaises(HandlerException):
  147. dispatcher.emit(self, "event.hello.world")
  148. def test_subscribe_event_duplicate_wildcard_priority_allowed(self):
  149. # duplicate priorities for different wildcard namespaces allowed
  150. def my_callback(**kwargs):
  151. pass
  152. dispatcher = SimpleEventDispatcher()
  153. dispatcher.intercept("event.hello.world", 1000, my_callback)
  154. dispatcher.intercept("someevent.hello.*", 1000, my_callback)
  155. # emit should work fine in this case with no exceptions
  156. dispatcher.emit(self, "event.hello.world")
  157. def test_subscribe_multiple_events(self):
  158. EVENT_NAME = "event.hello.world"
  159. callback_tracker = ['']
  160. def my_callback1(**kwargs):
  161. self.assertDictEqual(kwargs, {'sender': self,
  162. 'event_name': EVENT_NAME})
  163. callback_tracker[0] += "event1_"
  164. return "hello"
  165. def my_callback2(**kwargs):
  166. self.assertDictEqual(kwargs,
  167. {'sender': self,
  168. 'event_name': "event.hello.anotherworld"})
  169. callback_tracker[0] += "event2_"
  170. return "another"
  171. def my_callback3(**kwargs):
  172. self.assertDictEqual(kwargs,
  173. {'sender': self,
  174. 'event_name': "event.hello.anotherworld",
  175. 'next_handler': None})
  176. callback_tracker[0] += "event3_"
  177. return "world"
  178. dispatcher = SimpleEventDispatcher()
  179. dispatcher.observe(EVENT_NAME, 2000, my_callback1)
  180. # register to a different event with the same priority
  181. dispatcher.observe("event.hello.anotherworld", 2000, my_callback2)
  182. dispatcher.intercept("event.hello.anotherworld", 2020, my_callback3)
  183. result = dispatcher.emit(self, EVENT_NAME)
  184. self.assertEqual(
  185. callback_tracker[0], "event1_", "only `event.hello.world` handlers"
  186. " should have been triggered but received {0}".format(
  187. callback_tracker[0]))
  188. self.assertEqual(result, None, "Result should be `helloworld` "
  189. "as this is the expected return value from the chain")
  190. result = dispatcher.emit(self, "event.hello.anotherworld")
  191. self.assertEqual(
  192. callback_tracker[0], "event1_event2_event3_", "only handlers for"
  193. " event `event.hello.anotherworld` should have been triggered"
  194. " but received {0}".format(callback_tracker[0]))
  195. self.assertEqual(result, "world", "Result should be `world` "
  196. "as this is the expected return value from the chain")
  197. def test_subscribe_wildcard(self):
  198. callback_tracker = ['']
  199. def my_callback1(**kwargs):
  200. callback_tracker[0] += "event1_"
  201. return "hello" + kwargs.get('next_handler').invoke(**kwargs)
  202. def my_callback2(**kwargs):
  203. callback_tracker[0] += "event2_"
  204. return "some" + kwargs.get('next_handler').invoke(**kwargs)
  205. def my_callback3(**kwargs):
  206. callback_tracker[0] += "event3_"
  207. return "other" + kwargs.get('next_handler').invoke(**kwargs)
  208. def my_callback4(**kwargs):
  209. callback_tracker[0] += "event4_"
  210. return "world"
  211. dispatcher = SimpleEventDispatcher()
  212. dispatcher.intercept("event.*", 2000, my_callback1)
  213. # register to a different event with the same priority
  214. dispatcher.intercept("event.hello.*", 2010, my_callback2)
  215. dispatcher.intercept("event.hello.there", 2030, my_callback4)
  216. dispatcher.intercept("event.*.there", 2020, my_callback3)
  217. dispatcher.intercept("event.*.world", 2020, my_callback4)
  218. dispatcher.intercept("someevent.hello.there", 2030, my_callback3)
  219. # emit a series of events
  220. result = dispatcher.emit(self, "event.hello.there")
  221. self.assertEqual(
  222. callback_tracker[0], "event1_event2_event3_event4_",
  223. "Event handlers executed in unexpected order {0}".format(
  224. callback_tracker[0]))
  225. self.assertEqual(result, "hellosomeotherworld")
  226. result = dispatcher.emit(self, "event.test.hello.world")
  227. self.assertEqual(
  228. callback_tracker[0], "event1_event2_event3_event4_event1_event4_",
  229. "Event handlers executed in unexpected order {0}".format(
  230. callback_tracker[0]))
  231. self.assertEqual(result, "helloworld")
  232. # make sure cache gets invalidated when subscribing after emit
  233. def test_subscribe_after_emit(self):
  234. callback_tracker = ['']
  235. def my_callback1(**kwargs):
  236. callback_tracker[0] += "event1_"
  237. if kwargs.get('next_handler'):
  238. return "hello" + kwargs.get('next_handler').invoke(**kwargs)
  239. else:
  240. return "hello"
  241. def my_callback2(**kwargs):
  242. callback_tracker[0] += "event2_"
  243. return "some"
  244. dispatcher = SimpleEventDispatcher()
  245. dispatcher.intercept("event.hello.world", 1000, my_callback1)
  246. dispatcher.emit(self, "event.hello.world")
  247. dispatcher.intercept("event.hello.*", 1001, my_callback2)
  248. result = dispatcher.emit(self, "event.hello.world")
  249. self.assertEqual(
  250. callback_tracker[0], "event1_event1_event2_",
  251. "Event handlers executed in unexpected order {0}".format(
  252. callback_tracker[0]))
  253. self.assertEqual(result, "hellosome")