| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471 |
- import unittest
- from cloudbridge.cloud.base.events import SimpleEventDispatcher
- from cloudbridge.cloud.interfaces.events import EventHandler
- from cloudbridge.cloud.interfaces.exceptions import HandlerException
- class EventSystemTestCase(unittest.TestCase):
- def test_emit_event_no_handlers(self):
- dispatcher = SimpleEventDispatcher()
- result = dispatcher.dispatch(self, "event.hello.world")
- self.assertIsNone(result, "Result should be none as there are no"
- "registered handlers")
- def test_emit_event_observing_handler(self):
- EVENT_NAME = "event.hello.world"
- callback_tracker = ['']
- def my_callback(event_args, *args, **kwargs):
- self.assertDictEqual(event_args,
- {'sender': self,
- 'event': EVENT_NAME})
- self.assertSequenceEqual(args, ['first_pos_arg'])
- self.assertDictEqual(kwargs, {'a_keyword_arg': 'another_thing'})
- callback_tracker[0] += 'obs'
- return "hello"
- dispatcher = SimpleEventDispatcher()
- handler = dispatcher.observe(event_pattern=EVENT_NAME, priority=1000,
- callback=my_callback)
- assert handler.event_pattern == EVENT_NAME
- assert handler.priority == 1000
- assert handler.callback == my_callback
- self.assertIsInstance(handler, EventHandler)
- result = dispatcher.dispatch(self, EVENT_NAME, 'first_pos_arg',
- a_keyword_arg='another_thing')
- self.assertEqual(
- callback_tracker[0], "obs", "callback should have been invoked"
- "once and contain value `obs` but tracker value is {0}".format(
- callback_tracker[0]))
- self.assertIsNone(result, "Result should be none as this is an"
- " observing handler")
- def test_emit_event_intercepting_handler(self):
- EVENT_NAME = "event.hello.world"
- callback_tracker = ['']
- def my_callback(event_args, *args, **kwargs):
- self.assertDictEqual(event_args,
- {'sender': self,
- 'event': EVENT_NAME,
- 'next_handler': None})
- self.assertSequenceEqual(args, ['first_pos_arg'])
- self.assertDictEqual(kwargs, {'a_keyword_arg': 'another_thing'})
- callback_tracker[0] += "intcpt"
- return "world"
- dispatcher = SimpleEventDispatcher()
- handler = dispatcher.intercept(event_pattern=EVENT_NAME, priority=1000,
- callback=my_callback)
- self.assertIsInstance(handler, EventHandler)
- result = dispatcher.dispatch(self, EVENT_NAME, 'first_pos_arg',
- a_keyword_arg='another_thing')
- self.assertEqual(
- callback_tracker[0], "intcpt", "callback should have been invoked"
- "once and contain value `intcpt` but tracker value is {0}".format(
- callback_tracker[0]))
- self.assertEqual(result, "world", "Result should be `world` as this"
- " is an intercepting handler")
- def test_emit_event_implementing_handler(self):
- EVENT_NAME = "event.hello.world"
- callback_tracker = ['']
- def my_callback(*args, **kwargs):
- self.assertSequenceEqual(args, ['first_pos_arg'])
- self.assertDictEqual(kwargs, {'a_keyword_arg': 'another_thing'})
- callback_tracker[0] += "impl"
- return "world"
- dispatcher = SimpleEventDispatcher()
- handler = dispatcher.implement(event_pattern=EVENT_NAME, priority=1000,
- callback=my_callback)
- self.assertIsInstance(handler, EventHandler)
- result = dispatcher.dispatch(self, EVENT_NAME, 'first_pos_arg',
- a_keyword_arg='another_thing')
- self.assertEqual(
- callback_tracker[0], "impl", "callback should have been invoked"
- "once and contain value `intcpt` but tracker value is {0}".format(
- callback_tracker[0]))
- self.assertEqual(result, "world", "Result should be `world` as this"
- " is an implementing handler")
- def test_emit_event_observe_precedes_intercept(self):
- EVENT_NAME = "event.hello.world"
- callback_tracker = ['']
- def my_callback_obs(event_args, *args, **kwargs):
- self.assertDictEqual(event_args,
- {'sender': self,
- 'event': EVENT_NAME})
- self.assertSequenceEqual(args, ['first_pos_arg'])
- self.assertDictEqual(kwargs, {'a_keyword_arg': 'another_thing'})
- callback_tracker[0] += "obs_"
- return "hello"
- def my_callback_intcpt(event_args, *args, **kwargs):
- self.assertDictEqual(event_args,
- {'sender': self,
- 'event': EVENT_NAME,
- 'next_handler': None})
- self.assertSequenceEqual(args, ['first_pos_arg'])
- self.assertDictEqual(kwargs, {'a_keyword_arg': 'another_thing'})
- callback_tracker[0] += "intcpt_"
- return "world"
- dispatcher = SimpleEventDispatcher()
- dispatcher.observe(EVENT_NAME, 1000, my_callback_obs)
- dispatcher.intercept(EVENT_NAME, 1001, my_callback_intcpt)
- result = dispatcher.dispatch(self, EVENT_NAME, 'first_pos_arg',
- a_keyword_arg='another_thing')
- self.assertEqual(
- callback_tracker[0], "obs_intcpt_", "callback was not invoked in "
- "expected order. Should have been obs_intcpt_ but is {0}".format(
- callback_tracker[0]))
- self.assertEqual(result, "world", "Result should be `world` as this"
- " is the return value of the intercepting handler")
- def test_emit_event_observe_follows_intercept(self):
- EVENT_NAME = "event.hello.world"
- callback_tracker = ['']
- def my_callback_intcpt(event_args, *args, **kwargs):
- self.assertSequenceEqual(args, ['first_pos_arg'])
- self.assertDictEqual(kwargs, {'a_keyword_arg': 'another_thing'})
- self.assertEqual(event_args.get('sender'), self)
- self.assertEqual(event_args.get('next_handler').priority, 1001)
- self.assertEqual(event_args.get('next_handler').callback.__name__,
- "my_callback_obs")
- callback_tracker[0] += "intcpt_"
- # invoke next handler
- next_handler = event_args.get('next_handler')
- assert next_handler.priority == 1001
- assert next_handler.event_pattern == EVENT_NAME
- assert next_handler.callback == my_callback_obs
- retval = next_handler.invoke(event_args, *args, **kwargs)
- self.assertIsNone(retval, "Return values of observable handlers"
- " should not be propagated.")
- return "world"
- def my_callback_obs(event_args, *args, **kwargs):
- self.assertSequenceEqual(args, ['first_pos_arg'])
- self.assertDictEqual(kwargs, {'a_keyword_arg': 'another_thing'})
- self.assertDictEqual(event_args,
- {'sender': self,
- 'event': EVENT_NAME})
- callback_tracker[0] += "obs_"
- return "hello"
- dispatcher = SimpleEventDispatcher()
- # register priorities out of order to test that too
- dispatcher.observe(EVENT_NAME, 1001, my_callback_obs)
- dispatcher.intercept(EVENT_NAME, 1000, my_callback_intcpt)
- result = dispatcher.dispatch(self, EVENT_NAME, 'first_pos_arg',
- a_keyword_arg='another_thing')
- self.assertEqual(
- callback_tracker[0], "intcpt_obs_", "callback was not invoked in "
- "expected order. Should have been intcpt_obs_ but is {0}".format(
- callback_tracker[0]))
- self.assertEqual(result, "world", "Result should be `world` as this"
- " is the return value of the intercepting handler")
- def test_emit_event_intercept_follows_intercept(self):
- EVENT_NAME = "event.hello.world"
- callback_tracker = ['']
- def my_callback_intcpt1(event_args, *args, **kwargs):
- self.assertEqual(event_args.get('sender'), self)
- next_handler = event_args.get('next_handler')
- self.assertEqual(next_handler.priority, 2020)
- self.assertEqual(next_handler.callback.__name__,
- "my_callback_intcpt2")
- callback_tracker[0] += "intcpt1_"
- # invoke next handler but ignore return value
- return "hello" + next_handler.invoke(event_args, *args, **kwargs)
- def my_callback_intcpt2(event_args, *args, **kwargs):
- self.assertDictEqual(event_args,
- {'sender': self,
- 'event': EVENT_NAME,
- 'next_handler': None})
- callback_tracker[0] += "intcpt2_"
- return "world"
- dispatcher = SimpleEventDispatcher()
- dispatcher.intercept(EVENT_NAME, 2000, my_callback_intcpt1)
- dispatcher.intercept(EVENT_NAME, 2020, my_callback_intcpt2)
- result = dispatcher.dispatch(self, EVENT_NAME)
- self.assertEqual(
- callback_tracker[0], "intcpt1_intcpt2_", "callback was not invoked"
- " in expected order. Should have been intcpt1_intcpt2_ but is"
- " {0}".format(callback_tracker[0]))
- self.assertEqual(result, "helloworld", "Result should be `helloworld` "
- "as this is the expected return value from the chain")
- def test_emit_event_implement_follows_intercept(self):
- EVENT_NAME = "event.hello.world"
- callback_tracker = ['']
- def my_callback_intcpt(event_args, *args, **kwargs):
- self.assertEqual(event_args.get('sender'), self)
- next_handler = event_args.get('next_handler')
- self.assertEqual(next_handler.priority, 2020)
- self.assertEqual(next_handler.callback.__name__,
- "my_callback_impl")
- callback_tracker[0] += "intcpt_"
- # invoke next handler but ignore return value
- return "hello" + next_handler.invoke(event_args, *args, **kwargs)
- def my_callback_impl(*args, **kwargs):
- self.assertSequenceEqual(args, ['first_pos_arg'])
- self.assertDictEqual(kwargs, {'a_keyword_arg': 'another_thing'})
- callback_tracker[0] += "impl_"
- return "world"
- dispatcher = SimpleEventDispatcher()
- dispatcher.intercept(EVENT_NAME, 2000, my_callback_intcpt)
- dispatcher.implement(EVENT_NAME, 2020, my_callback_impl)
- result = dispatcher.dispatch(self, EVENT_NAME, 'first_pos_arg',
- a_keyword_arg='another_thing')
- self.assertEqual(
- callback_tracker[0], "intcpt_impl_", "callback was not invoked"
- " in expected order. Should have been intcpt_impl_ but is"
- " {0}".format(callback_tracker[0]))
- self.assertEqual(result, "helloworld", "Result should be `helloworld` "
- "as this is the expected return value from the chain")
- def test_emit_event_implement_precedes_intercept(self):
- EVENT_NAME = "event.hello.world"
- callback_tracker = ['']
- def my_callback_intcpt(event_args, *args, **kwargs):
- # Impl result should be accessible to intercepts that follow
- self.assertDictEqual(event_args,
- {'sender': self,
- 'event': EVENT_NAME,
- 'result': 'world',
- 'next_handler': None})
- self.assertSequenceEqual(args, ['first_pos_arg'])
- self.assertDictEqual(kwargs, {'a_keyword_arg': 'another_thing'})
- callback_tracker[0] += "intcpt_"
- return "hello"
- def my_callback_impl(*args, **kwargs):
- self.assertSequenceEqual(args, ['first_pos_arg'])
- self.assertDictEqual(kwargs, {'a_keyword_arg': 'another_thing'})
- callback_tracker[0] += "impl_"
- return "world"
- dispatcher = SimpleEventDispatcher()
- dispatcher.implement(EVENT_NAME, 2000, my_callback_impl)
- dispatcher.intercept(EVENT_NAME, 2020, my_callback_intcpt)
- result = dispatcher.dispatch(self, EVENT_NAME, 'first_pos_arg',
- a_keyword_arg='another_thing')
- self.assertEqual(
- callback_tracker[0], "impl_intcpt_", "callback was not invoked"
- " in expected order. Should have been intcpt_intcpt_ but is"
- " {0}".format(callback_tracker[0]))
- self.assertEqual(result, "world", "Result should be `world` "
- "as this is the expected return value from the chain")
- def test_subscribe_event_duplicate_priority(self):
- def my_callback(event_args, *args, **kwargs):
- pass
- dispatcher = SimpleEventDispatcher()
- dispatcher.intercept("event.hello.world", 1000, my_callback)
- dispatcher.intercept("event.hello.world", 1000, my_callback)
- with self.assertRaises(HandlerException):
- dispatcher.dispatch(self, "event.hello.world")
- def test_subscribe_event_duplicate_wildcard_priority(self):
- def my_callback(event_args, *args, **kwargs):
- pass
- dispatcher = SimpleEventDispatcher()
- dispatcher.intercept("event.hello.world", 1000, my_callback)
- dispatcher.intercept("event.hello.*", 1000, my_callback)
- with self.assertRaises(HandlerException):
- dispatcher.dispatch(self, "event.hello.world")
- def test_subscribe_event_duplicate_wildcard_priority_allowed(self):
- # duplicate priorities for different wildcard namespaces allowed
- def my_callback(event_args, *args, **kwargs):
- pass
- dispatcher = SimpleEventDispatcher()
- dispatcher.intercept("event.hello.world", 1000, my_callback)
- dispatcher.intercept("someevent.hello.*", 1000, my_callback)
- # emit should work fine in this case with no exceptions
- dispatcher.dispatch(self, "event.hello.world")
- def test_subscribe_multiple_events(self):
- EVENT_NAME = "event.hello.world"
- callback_tracker = ['']
- def my_callback1(event_args, *args, **kwargs):
- self.assertDictEqual(event_args, {'sender': self,
- 'event': EVENT_NAME})
- callback_tracker[0] += "event1_"
- return "hello"
- def my_callback2(event_args, *args, **kwargs):
- self.assertDictEqual(event_args,
- {'sender': self,
- 'event': "event.hello.anotherworld"})
- callback_tracker[0] += "event2_"
- return "another"
- def my_callback3(event_args, *args, **kwargs):
- self.assertDictEqual(event_args,
- {'sender': self,
- 'event': "event.hello.anotherworld",
- 'next_handler': None})
- callback_tracker[0] += "event3_"
- return "world"
- dispatcher = SimpleEventDispatcher()
- dispatcher.observe(EVENT_NAME, 2000, my_callback1)
- # register to a different event with the same priority
- dispatcher.observe("event.hello.anotherworld", 2000, my_callback2)
- dispatcher.intercept("event.hello.anotherworld", 2020, my_callback3)
- result = dispatcher.dispatch(self, EVENT_NAME)
- self.assertEqual(
- callback_tracker[0], "event1_", "only `event.hello.world` handlers"
- " should have been triggered but received {0}".format(
- callback_tracker[0]))
- self.assertEqual(result, None, "Result should be `helloworld` "
- "as this is the expected return value from the chain")
- result = dispatcher.dispatch(self, "event.hello.anotherworld")
- self.assertEqual(
- callback_tracker[0], "event1_event2_event3_", "only handlers for"
- " event `event.hello.anotherworld` should have been triggered"
- " but received {0}".format(callback_tracker[0]))
- self.assertEqual(result, "world", "Result should be `world` "
- "as this is the expected return value from the chain")
- def test_subscribe_wildcard(self):
- callback_tracker = ['']
- def my_callback1(event_args, *args, **kwargs):
- callback_tracker[0] += "event1_"
- next_handler = event_args.get('next_handler')
- return "hello" + next_handler.invoke(event_args, *args, **kwargs)
- def my_callback2(event_args, *args, **kwargs):
- callback_tracker[0] += "event2_"
- next_handler = event_args.get('next_handler')
- return "some" + next_handler.invoke(event_args, *args, **kwargs)
- def my_callback3(event_args, *args, **kwargs):
- callback_tracker[0] += "event3_"
- next_handler = event_args.get('next_handler')
- return "other" + next_handler.invoke(event_args, *args, **kwargs)
- def my_callback4(*args, **kwargs):
- callback_tracker[0] += "event4_"
- return "world"
- dispatcher = SimpleEventDispatcher()
- dispatcher.intercept("event.*", 2000, my_callback1)
- # register to a different event with the same priority
- dispatcher.intercept("event.hello.*", 2010, my_callback2)
- dispatcher.intercept("event.hello.there", 2030, my_callback4)
- dispatcher.intercept("event.*.there", 2020, my_callback3)
- dispatcher.intercept("event.*.world", 2020, my_callback4)
- dispatcher.intercept("someevent.hello.there", 2030, my_callback3)
- # emit a series of events
- result = dispatcher.dispatch(self, "event.hello.there")
- self.assertEqual(
- callback_tracker[0], "event1_event2_event3_event4_",
- "Event handlers executed in unexpected order {0}".format(
- callback_tracker[0]))
- self.assertEqual(result, "hellosomeotherworld")
- result = dispatcher.dispatch(self, "event.test.hello.world")
- self.assertEqual(
- callback_tracker[0], "event1_event2_event3_event4_event1_event4_",
- "Event handlers executed in unexpected order {0}".format(
- callback_tracker[0]))
- self.assertEqual(result, "helloworld")
- # make sure cache gets invalidated when subscribing after emit
- def test_subscribe_after_emit(self):
- callback_tracker = ['']
- def my_callback1(event_args, *args, **kwargs):
- callback_tracker[0] += "event1_"
- next_handler = event_args.get('next_handler')
- if next_handler:
- return "hello" + next_handler.invoke(
- event_args, *args, **kwargs)
- else:
- return "hello"
- def my_callback2(*args, **kwargs):
- callback_tracker[0] += "event2_"
- return "some"
- dispatcher = SimpleEventDispatcher()
- dispatcher.intercept("event.hello.world", 1000, my_callback1)
- dispatcher.dispatch(self, "event.hello.world")
- dispatcher.intercept("event.hello.*", 1001, my_callback2)
- result = dispatcher.dispatch(self, "event.hello.world")
- self.assertEqual(
- callback_tracker[0], "event1_event1_event2_",
- "Event handlers executed in unexpected order {0}".format(
- callback_tracker[0]))
- self.assertEqual(result, "hellosome")
- def test_unubscribe(self):
- EVENT_NAME = "event.hello.world"
- callback_tracker = ['']
- def my_callback1(event_args, *args, **kwargs):
- callback_tracker[0] += "event1_"
- next_handler = event_args.get('next_handler')
- if next_handler:
- return "hello" + next_handler.invoke(
- event_args, *args, **kwargs)
- else:
- return "hello"
- def my_callback2(*args, **kwargs):
- callback_tracker[0] += "event2_"
- return "some"
- dispatcher = SimpleEventDispatcher()
- hndlr1 = dispatcher.intercept(EVENT_NAME, 1000, my_callback1)
- dispatcher.dispatch(self, EVENT_NAME)
- hndlr2 = dispatcher.intercept("event.hello.*", 1001, my_callback2)
- # Both handlers should be registered
- self.assertListEqual(
- [my_callback1, my_callback2],
- [handler.callback for handler in
- dispatcher.get_handlers_for_event(EVENT_NAME)])
- hndlr1.unsubscribe()
- # Only my_callback2 should be registered after unsubscribe
- self.assertListEqual(
- [my_callback2],
- [handler.callback for handler in
- dispatcher.get_handlers_for_event(EVENT_NAME)])
- result = dispatcher.dispatch(self, EVENT_NAME)
- self.assertEqual(
- callback_tracker[0], "event1_event2_",
- "Event handlers executed in unexpected order {0}".format(
- callback_tracker[0]))
- self.assertEqual(result, "some")
- hndlr2.unsubscribe()
- result = dispatcher.dispatch(self, "event.hello.world")
- self.assertEqual(result, None)
|