def test_When_complex_concurrent_scenario_The_shit_works_2(self): ruleset = RuleSet([(rule1, { 'id': 'rule1', 'maxCount': 1 }), (rule3, { 'id': 'rule3', 'maxCount': 2 })], self.context) # matches evt #1 in rule3 instance 1 # ie. event-3.1-seen = 1 ruleset.onEvent(Event(service='tellstick', key='switch-1')) time.sleep(0.1) # matches evt #1 in rule1 instance 1 # and next evt (#2) in rule3 instance 1 - but it is busy so nothing happens # ie. event-1.1-seen = 1 ruleset.onEvent(Event(service='tellstick', key='switch-2')) time.sleep(0.3) # matches evt #1 in rule3 instance 2 # ie. event-3.1-seen = 2 ruleset.onEvent(Event(service='tellstick', key='switch-1')) time.sleep(0.1) # matches evt #1 in rule1, which is done, so new is spawned # and matches next evt (#2) in rule3 instance 1 that is now done running actions # and matches next evt (#2) in rule3 instance 2 but it is busy # ie. event-1.1-seen = 2 and event-3.2-seen = 2 ruleset.onEvent(Event(service='tellstick', key='switch-2')) time.sleep(0.3) self.assertEqual(self.context.test['event-1.1-seen'], 2) self.assertEqual(self.context.test['event-3.1-seen'], 2) self.assertEqual(self.context.test['event-3.2-seen'], 1)
def test_When_rule_is_busy_It_does_not_process_events(self): runner = RuleRunner('rule3', self.context, rule3, None) # At this point, rule is waiting for events, so this event is processed runner.onEvent(Event(service='tellstick', key='switch-1')) # At this point, "action" from step 1 is running, and it takes 0.3 sec # so the event we send now should be ignored since rule is busy running action runner.onEvent(Event(service='tellstick', key='switch-2')) # Wait for action (step 1) to complete runner.wait() # Conclusion: Rule should have processed first event but not second self.assertTrue(self.context.test.has_key('event-3.1-seen')) self.assertFalse(self.context.test.has_key('event-3.2-seen')) # At this point rule is waiting for events again, so if we send # event 2 again now, it should be processed runner.onEvent(Event(service='tellstick', key='switch-2')) runner.wait() self.assertTrue(self.context.test.has_key('event-3.1-seen')) self.assertTrue(self.context.test.has_key('event-3.2-seen'))
def test_When_complex_concurrent_scenario_The_shit_works(self): ruleset = RuleSet([(rule1, { 'id': 'rule1', 'maxCount': 1 }), (rule2, { 'id': 'rule2', 'maxCount': 1 }), (rule3, { 'id': 'rule3', 'maxCount': 1 })], self.context) ruleset.onEvent(Event(service='tellstick', key='switch-1')) time.sleep(0.1) ruleset.onEvent(Event(service='tellstick', key='switch-2')) time.sleep(0.3) ruleset.onEvent(Event(service='tellstick', key='switch-3')) time.sleep(0.3) self.assertTrue(self.context.test.has_key('event-1.1-seen')) self.assertTrue(self.context.test.has_key('event-2.1-seen')) self.assertTrue(self.context.test.has_key('event-2.2-seen')) self.assertTrue(self.context.test.has_key('event-2.3-seen')) self.assertTrue(self.context.test.has_key('event-3.1-seen'))
def test_When_maxcount_is_two_Two_and_only_two_runners_are_spawned(self): inst = RuleInstances('rule2', rule2, 2, self.context) self.assertEqual(len(inst.runners), 0) inst.onEvent(Event(service='tellstick', key='switch-1')) self.assertEqual(len(inst.runners), 1) inst.onEvent(Event(service='tellstick', key='switch-1')) self.assertEqual(len(inst.runners), 2) inst.onEvent(Event(service='tellstick', key='switch-1')) self.assertEqual(len(inst.runners), 2)
def test_When_matching_exact_incorrect_values_They_are_not_matched(self): e1 = Event(service='srv', key='key', data='data') e2 = Event(service='srv1', key='key1', data='data1') self.assertFalse(e1.match(e2)) e2 = Event(service='srv1', key='key', data='data') self.assertFalse(e1.match(e2)) e2 = Event(service='srv', key='key1', data='data') self.assertFalse(e1.match(e2)) e2 = Event(service='srv', key='key', data='data1') self.assertFalse(e1.match(e2))
def test_When_all_events_are_matched_The_runner_is_removed(self): inst = RuleInstances('rule2', rule2, 1, self.context) self.assertEqual(len(inst.runners), 0) inst.onEvent(Event(service='tellstick', key='switch-1')) inst.wait() self.assertEqual(len(inst.runners), 1) inst.onEvent(Event(service='tellstick', key='switch-2')) inst.wait() self.assertEqual(len(inst.runners), 0)
def test_When_event_rule_does_not_wait_for_occurs_Rule_does_not_iterate_to_next_step( self): runner = RuleRunner('rule1', self.context, rule1, None) self.assertFalse(self.context.test.has_key('event-seen')) runner.onEvent(Event(service='tellstick', key='switch-3')) runner.wait() self.assertFalse(self.context.test.has_key('event-1.1-seen'))
def test_When_rule_stops_before_end_It_still_runs_complete(self): self.context.state.set('timer.hour.data.value', 15) # !! runner = RuleRunner('rule2', self.context, rule2, None) self.assertFalse(self.context.test.has_key('complete')) runner.onEvent(Event(service='tellstick', key='switch-1')) runner.wait() self.assertFalse(self.context.test.has_key('complete')) runner.onEvent(Event(service='tellstick', key='switch-2')) runner.wait() self.assertTrue(self.context.test.has_key('complete'))
def test_When_event_occurs_They_are_passed_to_runner(self): inst = RuleInstances('rule2', rule2, 1, self.context) self.assertFalse(self.context.test.has_key('event-2.1-seen')) self.assertFalse(self.context.test.has_key('event-2.2-seen')) inst.onEvent(Event(service='tellstick', key='switch-1')) if len(inst.runners) > 0: inst.runners[0].wait() self.assertTrue(self.context.test.has_key('event-2.1-seen')) self.assertFalse(self.context.test.has_key('event-2.2-seen')) inst.onEvent(Event(service='tellstick', key='switch-2')) if len(inst.runners) > 0: inst.runners[0].wait() self.assertTrue(self.context.test.has_key('event-2.1-seen')) self.assertTrue(self.context.test.has_key('event-2.2-seen'))
def test_When_rule_conditional_does_not_match_It_stops(self): # Rule checks hour >= 16 before last event, so when # hour is 15, it should only do event1 + event2 self.context.state.set('timer.hour.data.value', 15) runner = RuleRunner('rule2', self.context, rule2, None) runner.onEvent(Event(service='tellstick', key='switch-1')) runner.wait() runner.onEvent(Event(service='tellstick', key='switch-2')) runner.wait() runner.onEvent(Event(service='tellstick', key='switch-3')) runner.wait() self.assertTrue(self.context.test.has_key('event-2.1-seen')) self.assertTrue(self.context.test.has_key('event-2.2-seen')) self.assertFalse(self.context.test.has_key('event-2.3-seen'))
def test_When_rule_has_many_events_It_iterates_correctly(self): self.context.state.set('timer.hour.data.value', 17) runner = RuleRunner('rule2', self.context, rule2, None) # Before any events, rule does nothing self.assertFalse(self.context.test.has_key('event-2.1-seen')) self.assertFalse(self.context.test.has_key('event-2.2-seen')) self.assertFalse(self.context.test.has_key('event-2.3-seen')) # When event that is not in rule occurs, nothing happens runner.onEvent(Event(service='tellstick', key='foo')) runner.wait() self.assertFalse(self.context.test.has_key('event-2.1-seen')) self.assertFalse(self.context.test.has_key('event-2.2-seen')) self.assertFalse(self.context.test.has_key('event-2.3-seen')) # When event occurs that matches first event in rule, it iterates to next step runner.onEvent(Event(service='tellstick', key='switch-1')) runner.wait() self.assertTrue(self.context.test.has_key('event-2.1-seen')) self.assertFalse(self.context.test.has_key('event-2.2-seen')) self.assertFalse(self.context.test.has_key('event-2.3-seen')) # When another event that is not in rule occurs, nothing happens runner.onEvent(Event(service='tellstick', key='foo')) runner.wait() self.assertTrue(self.context.test.has_key('event-2.1-seen')) self.assertFalse(self.context.test.has_key('event-2.2-seen')) self.assertFalse(self.context.test.has_key('event-2.3-seen')) # When event occurs that matches second event in rule, it iterates another step runner.onEvent(Event(service='tellstick', key='switch-2')) runner.wait() self.assertTrue(self.context.test.has_key('event-2.2-seen')) self.assertFalse(self.context.test.has_key('event-2.3-seen')) # When event occurs that matches third event in rule, it iterates another step runner.onEvent(Event(service='tellstick', key='switch-3')) runner.wait() self.assertTrue(self.context.test.has_key('event-2.3-seen'))
def test_When_event_is_matched_The_yield_returns_the_event(self): runner = RuleRunner('rule4', self.context, rule4, None) self.assertFalse(self.context.test.has_key('matched-event')) runner.onEvent( Event(service='tellstick', key='switch-1', data={ 'value': 'xyz', 'other': 'foo' })) runner.wait() self.assertTrue(self.context.test.has_key('matched-event')) self.assertEqual(self.context.test['matched-event'].key, 'switch-1') self.assertEqual(self.context.test['matched-event'].data['value'], 'xyz') self.assertEqual(self.context.test['matched-event'].data['other'], 'foo')
def test_When_passing_invalid_kwargs_TypeError_is_raised(self): try: e = Event(foo='invalid') except TypeError: return raise Exception('Expected TypeError, got none')
def test_When_events_have_different_times_They_are_still_matched(self): e1 = Event(service='srv', key='key', time=1234) e2 = Event(service='srv', key='key', time=2345) self.assertTrue(e1.match(e2))
def test_When_passing_valid_positional_args_They_are_set(self): e = Event('srv', 'dev', 'key', 'data') self.assertEqual(e.service, 'srv') self.assertEqual(e.device, 'dev') self.assertEqual(e.key, 'key') self.assertEqual(e.data, 'data')
def test_When_deep_data_matches_wildcard_It_is_a_match(self): e1 = Event(service='srv', key='key', data={'value': 2, 'extra': {'type': 'humidity'}}) # occurring e2 = Event(service='srv', key='key', data={'value': 2, 'extra': {'type': '*'}}) # rule self.assertTrue(e1.match(e2))
def test_When_deep_occurring_data_is_subset_of_configured_data_It_is_not_a_match_2(self): e1 = Event(service='srv', key='key', data={'value': 2, 'extra': {}}) # occurring e2 = Event(service='srv', key='key', data={'value': 2, 'extra': {'type': 'humidity'}}) # rule self.assertFalse(e1.match(e2))
def test_When_passing_valid_kwargs_They_are_set(self): e = Event(service='srv', device='dev', key='key', data='data') self.assertEqual(e.service, 'srv') self.assertEqual(e.device, 'dev') self.assertEqual(e.key, 'key') self.assertEqual(e.data, 'data')
def test_When_rule_has_more_events_It_is_not_complete(self): runner = RuleRunner('rule1', self.context, rule1, None) self.assertFalse(runner.isComplete) runner.onEvent(Event(service='tellstick', key='switch-3')) runner.wait() self.assertFalse(runner.isComplete)
def test_When_matching_list_where_no_events_match_It_does_not_matches(self): e1 = Event(service='srv', key='key', data='data') e2 = Event(service='srv', key='key', data='data1') e3 = Event(service='srv', key='key', data='data2') self.assertFalse(e1.match([e2,e3]))
def test_When_matching_wildcards_and_exact_incorrect_values_They_are_not_matched(self): e1 = Event(service='srv', key='*', data='*') e2 = Event(service='srv1', key='key', data={'value': 12}) self.assertFalse(e1.match(e2))
def test_When_leaving_some_args_out_They_are_set_to_wildcard(self): e = Event(key='foo') self.assertEqual(e.service, '*') self.assertEqual(e.device, '*') self.assertEqual(e.key, 'foo') self.assertEqual(e.data, '*')
def test_When_matching_exact_correct_values_They_are_matched(self): e1 = Event(service='srv', device='dev', key='key', data='data') e2 = Event(service='srv', device='dev', key='key', data='data') self.assertTrue(e1.match(e2))
def test_When_data_does_not_match_It_is_not_a_match(self): e1 = Event(service='srv', key='key', data={'value': 2, 'type': 'humidity1'}) # occurring e2 = Event(service='srv', key='key', data={'value': 2, 'type': 'humidity2'}) # rule self.assertFalse(e1.match(e2))
def test_When_matching_wildcards_They_are_matched(self): e1 = Event(service='srv', key='*', data='*') e2 = Event(service='srv', key='key', data={'value': 12}) self.assertTrue(e1.match(e2))
def test_When_configured_data_is_subset_of_occuring_data_It_is_a_match(self): e1 = Event(service='srv', key='key', data={'value': 2, 'type': 'humidity'}) # occurring e2 = Event(service='srv', key='key', data={'value': 2}) # rule self.assertTrue(e1.match(e2))
def test_When_matching_list_where_both_events_match_It_matches(self): e1 = Event(service='srv', key='key', data='data') e2 = Event(service='srv', key='key', data='data') e3 = Event(service='srv', key='key', data='data') self.assertTrue(e1.match([e2,e3]))
def test_When_occurring_data_is_subset_of_configured_data_with_wildcard_It_is_not_a_match(self): e1 = Event(service='srv', key='key', data={'value': 2}) # occurring e2 = Event(service='srv', key='key', data={'value': '*', 'type': 'humidity'}) # rule self.assertFalse(e1.match(e2))
def test_When_data_matches_exactly_It_is_a_match(self): e1 = Event(service='srv', key='key', data={'value': 2, 'type': 'humidity'}) # occurring e2 = Event(service='srv', key='key', data={'value': 2, 'type': 'humidity'}) # rule self.assertTrue(e1.match(e2))
def test_When_event_not_matching_first_occur_A_new_runner_is_not_spawned( self): inst = RuleInstances('rule2', rule2, 1, self.context) self.assertEqual(len(inst.runners), 0) inst.onEvent(Event(service='tellstick', key='foo')) self.assertEqual(len(inst.runners), 0)