def test_validate(): jsonschema = '''{ "type": "object", "properties": { "payload": { "type": "object", "properties": { "foo": { "type": "string" }, "bar": { "type": "number" } }, "required": ["foo", "bar"] } }, "required": ["payload"] }''' eventtype = EventType(jsonschema) # event is conforming to JSON schema of its type event = Event(eventtype, payload=dict(foo='value', bar=123)) assert EventType.validate(event, eventtype) # event is of another type event = Event(GenericEventType(), payload=dict(foo='value', bar=123)) assert not EventType.validate(event, eventtype) # event is of the same type but not conforming event = Event(eventtype, payload=dict(x=1, y=2)) assert not EventType.validate(event, eventtype)
def test_exception_bubbling(): # do propagate cfg['reactors']['propagate_exceptions'] = True brq = Baroque() brq.config = cfg def reaction_raising_error(evt): raise FileNotFoundError() r = Reactor(reaction_raising_error) brq.on(GenericEventType()).run(r) with pytest.raises(FileNotFoundError): brq.publish(Event(GenericEventType())) pytest.fail() # do not propagate cfg['reactors']['propagate_exceptions'] = False brq = Baroque() brq.config = cfg brq.on(GenericEventType()).run(r) try: brq.publish(Event(GenericEventType())) except FileNotFoundError: pytest.fail()
def test_reset(): brq = Baroque() class MyEventType1(EventType): def __init__(self, owner=None): EventType.__init__(self, '''{ "$schema": "http://json-schema.org/draft-04/schema#" }''', description='test', owner=owner) class MyEventType2(EventType): def __init__(self, owner=None): EventType.__init__(self, '''{ "$schema": "http://json-schema.org/draft-04/schema#" }''', description='test', owner=owner) eventtype1 = MyEventType1() eventtype2 = MyEventType2() brq.on(eventtype1).run(ReactorFactory.stdout()) brq.on(eventtype2).run(ReactorFactory.stdout()) brq.publish(Event(eventtype1)) brq.publish(Event(eventtype2)) assert brq.events.count_all() == 2 assert brq.eventtypes.count() == 2 + len( DEFAULT_CONFIG['eventtypes']['pre_registered']) assert len(brq.reactors.registered_types) == 2 brq.reset() assert brq.events.count_all() == 0 assert brq.eventtypes.count() == 0 assert len(brq.reactors.registered_types) == 0
def test_update(): bck = DictBackend() evt = Event(GenericEventType(), dict(foo='bar')) bck.create(evt) assert len(bck._db) == 1 # updating nothing leads to an exception with pytest.raises(AssertionError): bck.update(None) pytest.fail() # updating events with null id is idempotent former_evt0_id = evt.id evt.id = None bck.update(evt) assert len(bck._db) == 1 result = bck.read(former_evt0_id) assert result == evt # event was unchanged assert result.owner is None # actual update evt.owner = 'me' bck.update(evt) assert len(bck._db) == 1 result = bck.read(former_evt0_id) assert result.owner == 'me'
def test_constructor_with_type_objects(): e1 = Event(GenericEventType(), payload=dict(a=1, b=2), description='hello', owner=1234) e2 = Event(GenericEventType, payload=dict(a=1, b=2), description='hello', owner=1234) assert isinstance(e1.type, GenericEventType) assert isinstance(e2.type, GenericEventType)
def test_magic_methods(): bck = DictBackend() evt1 = Event(GenericEventType(), dict(foo='bar')) evt2 = Event(MetricEventType(), dict(bar='baz')) bck.create(evt1) bck.create(evt2) assert len(bck) == 2 assert evt1 in bck assert evt2 in bck for event_id in bck: assert isinstance(bck[event_id], Event) keys = bck.keys() assert len(keys) == 2 assert evt1.id in keys assert evt2.id in keys values = bck.values() assert len(values) == 2 assert evt1 in values assert evt2 in values bck.clear() assert len(bck) == 0
def test_touch(): e = Event(GenericEventType(), payload=dict(a=1, b=2), description='hello', owner=1234) ts1 = e.timestamp e = Event(GenericEventType(), payload=dict(a=1, b=2), description='hello', owner=1234) ts2 = e.timestamp assert ts2 > ts1
def test_constructor_failures(): with pytest.raises(TypeError): Event() pytest.fail() with pytest.raises(AssertionError): Event(None) pytest.fail() with pytest.raises(AssertionError): Event(123) pytest.fail() with pytest.raises(AssertionError): Event(GenericEventType(), payload=123) pytest.fail()
def test_react_conditionally(): r = Reactor(greet, condition=only_test_events) evt = Event(GenericEventType()) # condition is not met r.react_conditionally(evt) assert r.count_reactions() == 0 assert r.last_event_reacted() is None assert r.last_reacted_on() is None # condition is met evt.payload = {'test': 'value'} r.react_conditionally(evt) assert r.count_reactions() == 1 assert r.last_event_reacted() is not None assert r.last_reacted_on() is not None
def test_condition_met(): r = Reactor(greet) evt = Event(GenericEventType(), payload=dict()) # no condition set is_met = r._condition_met(evt) assert is_met # condition is not met r.only_if(only_test_events) is_met = r._condition_met(evt) assert not is_met # condition is met evt.payload['test'] = 'value' is_met = r._condition_met(evt) assert is_met
def test_dont_count_twice_eventtypes(): eventtype = GenericEventType() same_eventtype = GenericEventType() c = EventCounter() assert c.count_all() == 0 assert c.count(eventtype) == c.count(same_eventtype) == 0 c.increment_counting(Event(eventtype)) assert c.count_all() == 1 assert c.count(eventtype) == 1 assert c.count(same_eventtype) == 1 c.increment_counting(Event(same_eventtype)) assert c.count_all() == 2 assert c.count(eventtype) == 2 assert c.count(same_eventtype) == 2
def test_persist_event(): brq = Baroque() assert len(brq._persistance_backend) == 0 evt = Event(GenericEventType(), payload=dict(test=123)) brq._persist_event(evt) assert len(brq._persistance_backend) == 1 assert evt in brq._persistance_backend
def test_react(): r = Reactor(greet) evt = Event(GenericEventType()) r.react(evt) assert r.count_reactions() == 1 assert r.last_event_reacted() is not None assert r.last_reacted_on() is not None
def test_update_event_status(): eventtype = GenericEventType() evt = Event(eventtype, payload=dict()) assert evt.status == EventStatus.UNPUBLISHED brq = Baroque() brq._update_event_status(evt) assert evt.status == EventStatus.PUBLISHED
def test_ignore_unregistered_eventtypes(): # do ignore cfg['eventtypes']['ignore_unregistered'] = True brq = Baroque() brq.config = cfg try: brq.publish(Event(GenericEventType())) except UnregisteredEventTypeError: pytest.fail() # do not ignore cfg['eventtypes']['ignore_unregistered'] = False brq = Baroque() brq.config = cfg with pytest.raises(UnregisteredEventTypeError): brq.publish(Event(FakeEventType())) pytest.fail()
def test_delete(): bck = DictBackend() evt1 = Event(GenericEventType(), dict(foo='bar')) evt2 = Event(MetricEventType(), dict(bar='baz')) bck.create(evt1) bck.create(evt2) assert len(bck._db) == 2 # deleting nothing bck.delete(None) assert len(bck._db) == 2 # deleting an actual event bck.delete(evt1.id) assert len(bck._db) == 1 result = bck.read(evt2.id) assert result == evt2
def test_read(): bck = DictBackend() evt = Event(GenericEventType(), dict(foo='bar')) bck.create(evt) result = bck.read(evt.id) assert result == evt # reading nothing assert bck.read('unexistent') is None
def test_constructor(): e = Event(GenericEventType(), payload=dict(a=1, b=2), description='hello', owner=1234) assert isinstance(e.type, GenericEventType) assert e.id is not None assert not e.links assert not e.tags assert e.status == EventStatus.UNPUBLISHED assert e.timestamp is not None
def test_events_counting(): eventtype1 = GenericEventType() eventtype2 =MetricEventType() c = EventCounter() assert c.count_all() == 0 assert c.count(eventtype1) == 0 assert c.count(eventtype2) == 0 c.increment_counting(Event(eventtype1)) assert c.count_all() == 1 assert c.count(eventtype1) == 1 assert c.count(eventtype2) == 0 c.increment_counting(Event(eventtype2)) assert c.count_all() == 2 assert c.count(eventtype1) == 1 assert c.count(eventtype2) == 1
def test_count_event(): brq = Baroque() eventtype = GenericEventType() evt = Event(eventtype, payload=dict()) assert brq.events.count(eventtype) == 0 assert brq.events.count_all() == 0 brq._count_event(evt) assert brq.events.count(eventtype) == 1 assert brq.events.count_all() == 1
def test_publish_on_topic(): reg = TopicsRegistry() t = Topic('test', eventtypes=[GenericEventType(), MetricEventType()]) evt = Event(MetricEventType()) # failures with pytest.raises(AssertionError): reg.publish_on_topic(None, t) with pytest.raises(AssertionError): reg.publish_on_topic(123, t) with pytest.raises(AssertionError): reg.publish_on_topic(evt, None) with pytest.raises(AssertionError): reg.publish_on_topic(evt, 123) # using a databox class to keep state and make assertions class Box: def __init__(self): self.called = False def mark_called(self): self.called = True # publish an event on a topic that doesn't have its eventtype registered t = Topic('aaa', eventtypes=[GenericEventType()]) evt = Event(MetricEventType()) box = Box() r = ReactorFactory.call_function(box, 'mark_called') reg.register(t) reg.on_topic_run(t, r) reg.publish_on_topic(evt, t) assert not box.called # publish an event on a topic that has its eventtype registered reg = TopicsRegistry() t = Topic('aaa', eventtypes=[MetricEventType()]) box = Box() r = ReactorFactory.call_function(box, 'mark_called') reg.register(t) reg.on_topic_run(t, r) evt = Event(MetricEventType()) reg.publish_on_topic(evt, t) assert box.called
def new(cls, **kwargs): """Factory method returning a generic type event. Args: **kwargs: positional arguments for `Event` instantiation Returns: :obj:`baroque.entities.event.Event` """ return Event(GenericEventType(), **kwargs)
def test_persist(): # persist events brq = Baroque() cfg['eventtypes']['ignore_unregistered'] = True cfg['eventtypes']['pre_registered'] = [ 'baroque.defaults.eventtypes.GenericEventType' ] cfg['topics']['register_on_binding'] = True cfg['events']['persist'] = True brq.config = cfg evt1 = Event(GenericEventType()) assert len(brq._persistance_backend) == 0 brq.publish(evt1) assert len(brq._persistance_backend) == 1 assert evt1 in brq._persistance_backend evt2 = Event(GenericEventType()) t = brq.topics.new('test-topic', eventtypes=[MetricEventType(), GenericEventType()]) assert len(brq._persistance_backend) == 1 brq.publish_on_topic(evt2, t) assert len(brq._persistance_backend) == 2 assert evt2 in brq._persistance_backend # do not persist events brq = Baroque() cfg['events']['persist'] = False brq.config = cfg evt3 = Event(GenericEventType()) assert len(brq._persistance_backend) == 0 brq.publish(evt3) assert len(brq._persistance_backend) == 0 evt4 = Event(GenericEventType()) t = brq.topics.new('test-topic', eventtypes=[MetricEventType(), GenericEventType()]) assert len(brq._persistance_backend) == 0 brq.publish_on_topic(evt4, t) assert len(brq._persistance_backend) == 0
def test_validate_event_schema(): brq = Baroque() et = MetricEventType() event_valid = Event(et, payload={ 'metric': 'temperature', 'value': 56.7793, 'timestamp': '2017-02-15T13:56:09Z' }) event_invalid = Event(et, payload={'metric': 'temperature'}) # Publish invalid event with pytest.raises(InvalidEventSchemaError): brq.publish(event_invalid) pytest.fail() # Publish valid event try: brq.publish(event_valid) except InvalidEventSchemaError: pytest.fail()
def test_create(): bck = DictBackend() assert len(bck._db) == 0 # adding nothing leads to an exception with pytest.raises(AssertionError): bck.create(None) pytest.fail() # adding events with null id evt0 = Event(GenericEventType(), dict(foo='bar')) evt0.id = None bck.create(evt0) assert len(bck._db) == 0 # fresh add evt1 = Event(GenericEventType(), dict(foo='bar')) bck.create(evt1) assert len(bck._db) == 1 # adding twice the same event is idempotent bck.create(evt1) assert len(bck._db) == 1
def test_persistence_backend(): brq = Baroque() # test we're actually using the claimed persistence backend cfg['events']['persist'] = True cfg['events'][ 'persistence_backend'] = 'tests.test_configuration.FakePersistenceBackend' brq.config = cfg pb = brq._persistance_backend assert len(pb) == 0 evt = Event(GenericEventType()) brq.publish(evt) assert len(pb) == 1 assert evt in pb
def test_fire(): # using a databox to keep state and make assertions box = Box() r1 = ReactorFactory.call_function(box, 'test_eventtype') r2 = ReactorFactory.call_function(box, 'any_eventtype') brq = Baroque() eventtype = GenericEventType() brq.on(eventtype).run(r1) brq.on_any_event_run(r2) evt = Event(eventtype) assert not box.reacted_on_test_eventtype assert not box.reacted_on_any_eventtype assert brq.events.count_all() == 0 brq.fire(evt) assert box.reacted_on_test_eventtype assert box.reacted_on_any_eventtype assert brq.events.count_all() == 1
def test_validate_schema(): cfg['eventtypes']['pre_registered'] = [ 'baroque.defaults.eventtypes.MetricEventType' ] brq = Baroque() brq.config = cfg et = MetricEventType() event = Event(et, payload=dict(a=1, b=2)) # do not validate cfg['events']['validate_schema'] = False brq.config = cfg try: brq.publish(event) except InvalidEventSchemaError: pytest.fail() # do validate cfg['events']['validate_schema'] = True with pytest.raises(InvalidEventSchemaError): brq.publish(event)
def test_publish_on_topic(): brq = Baroque() t = brq.topics.new('test-topic1', eventtypes=[MetricEventType(), GenericEventType()]) evt = Event(MetricEventType()) # trying to publish events to an unregistered topic with pytest.raises(UnregisteredTopicError): brq.publish_on_topic(evt, Topic('unregistered')) pytest.fail() # using a box to keep state and make assertions box = Box() brq.on_topic_run(t, ReactorFactory.call_function(box, 'mark_called')) assert not box.called assert brq.events.count_all() == 0 brq.publish_on_topic(evt, t) assert box.called assert brq.events.count_all() == 1 assert evt.status == EventStatus.PUBLISHED
def test_publish(): # using a databox to keep state and make assertions box = Box() r1 = ReactorFactory.call_function(box, 'test_eventtype') r2 = ReactorFactory.call_function(box, 'any_eventtype') brq = Baroque() eventtype = GenericEventType() brq.on(eventtype).run(r1) brq.on_any_event_run(r2) evt = Event(eventtype) assert not box.reacted_on_test_eventtype assert not box.reacted_on_any_eventtype assert brq.events.count_all() == 0 brq.publish(evt) assert box.reacted_on_test_eventtype assert box.reacted_on_any_eventtype assert brq.events.count_all() == 1 assert evt.status == EventStatus.PUBLISHED with pytest.raises(AssertionError): brq.publish('not-an-event') pytest.fail()