stacktach-winchester/tests/test_trigger_manager.py
Sandy Walsh ac49955386 Adding debugger from oahu
Allows for per-trigger-definition debugging. Simply add
debug_level=1 to your trigger definition.

debug_level=2 gives detailed explainations of why your
stream didn't fire or trigger.

This way, you can leave the overall debug level at INFO
and still get details on the stream you're working on.

Yagi worker now uses idle() callback for debug updates.

and minor cleanups for pep8/HACKING

Change-Id: Id0af7a0adbcc47335ad250130958932c708b5c18
2014-10-02 20:50:31 +00:00

270 lines
13 KiB
Python

import unittest2 as unittest
import mock
import datetime
import timex
from winchester import db as winch_db
from winchester import debugging
from winchester import definition
from winchester import trigger_manager
class TestTriggerManager(unittest.TestCase):
def setUp(self):
super(TestTriggerManager, self).setUp()
self.debugger = debugging.NoOpDebugger()
@mock.patch.object(trigger_manager.ConfigManager, 'wrap')
def test_save_event(self, mock_config_wrap):
tm = trigger_manager.TriggerManager('test')
tm.db = mock.MagicMock(spec=tm.db)
event = dict(message_id='1234-test-5678',
timestamp=datetime.datetime(2014,8,1,10,9,8,77777),
event_type='test.thing',
test_trait="foobar",
other_test_trait=42)
self.assertTrue(tm.save_event(event))
tm.db.create_event.assert_called_once_with('1234-test-5678', 'test.thing',
datetime.datetime(2014,8,1,10,9,8,77777),
dict(test_trait='foobar', other_test_trait=42))
@mock.patch.object(trigger_manager.ConfigManager, 'wrap')
def test_save_event_dup(self, mock_config_wrap):
tm = trigger_manager.TriggerManager('test')
tm.db = mock.MagicMock(spec=tm.db)
tm.db.create_event.side_effect = winch_db.DuplicateError("test boom!")
event = dict(message_id='1234-test-5678',
timestamp=datetime.datetime(2014,8,1,10,9,8,77777),
event_type='test.thing',
test_trait="foobar",
other_test_trait=42)
self.assertFalse(tm.save_event(event))
tm.db.create_event.assert_called_once_with('1234-test-5678', 'test.thing',
datetime.datetime(2014,8,1,10,9,8,77777),
dict(test_trait='foobar', other_test_trait=42))
@mock.patch('winchester.trigger_manager.EventCondenser', autospec=True)
@mock.patch.object(trigger_manager.ConfigManager, 'wrap')
def test_convert_notification(self, mock_config_wrap, mock_condenser):
tm = trigger_manager.TriggerManager('test')
tm.db = mock.MagicMock(spec=tm.db)
tm.distiller = mock.MagicMock(spec=tm.distiller)
test_event = "I'm a test event!"
tm.distiller.to_event.return_value = True
cond = mock_condenser.return_value
cond.validate.return_value = True
cond.get_event.return_value = test_event
tm.save_event = mock.MagicMock()
tm.save_event.return_value = True
res = tm.convert_notification('test notification here')
mock_condenser.assert_called_once_with(tm.db)
cond.clear.assert_called_once_with()
cond.validate.assert_called_once_with()
tm.distiller.to_event.assert_called_once_with('test notification here', cond)
self.assertEquals(res, test_event)
@mock.patch('winchester.trigger_manager.EventCondenser', autospec=True)
@mock.patch.object(trigger_manager.ConfigManager, 'wrap')
def test_convert_notification_dropped(self, mock_config_wrap, mock_condenser):
tm = trigger_manager.TriggerManager('test')
tm.db = mock.MagicMock(spec=tm.db)
tm.distiller = mock.MagicMock(spec=tm.distiller)
test_event = "I'm a test event!"
tm.distiller.to_event.return_value = False
cond = mock_condenser.return_value
cond.validate.return_value = True
cond.get_event.return_value = test_event
tm.save_event = mock.MagicMock()
tm.save_event.return_value = True
test_notif = dict(event_type='test.notification.here', message_id='4242-4242')
res = tm.convert_notification(test_notif)
mock_condenser.assert_called_once_with(tm.db)
cond.clear.assert_called_once_with()
self.assertFalse(cond.validate.called)
tm.distiller.to_event.assert_called_once_with(test_notif, cond)
self.assertFalse(tm.save_event.called)
self.assertIsNone(res)
@mock.patch('winchester.trigger_manager.EventCondenser', autospec=True)
@mock.patch.object(trigger_manager.ConfigManager, 'wrap')
def test_convert_notification_invalid(self, mock_config_wrap, mock_condenser):
tm = trigger_manager.TriggerManager('test')
tm.db = mock.MagicMock(spec=tm.db)
tm.distiller = mock.MagicMock(spec=tm.distiller)
test_event = "I'm a test event!"
tm.distiller.to_event.return_value = True
cond = mock_condenser.return_value
cond.validate.return_value = False
cond.get_event.return_value = test_event
tm.save_event = mock.MagicMock()
tm.save_event.return_value = True
test_notif = dict(event_type='test.notification.here', message_id='4242-4242')
res = tm.convert_notification(test_notif)
mock_condenser.assert_called_once_with(tm.db)
cond.clear.assert_called_once_with()
cond.validate.assert_called_once_with()
tm.distiller.to_event.assert_called_once_with(test_notif, cond)
self.assertFalse(tm.save_event.called)
self.assertIsNone(res)
@mock.patch.object(trigger_manager.ConfigManager, 'wrap')
def test_add_or_create_stream(self, mock_config_wrap):
tm = trigger_manager.TriggerManager('test')
tm.db = mock.MagicMock(spec=tm.db)
tm.db.get_active_stream.return_value = 'Existing Stream'
tm.current_time = mock.MagicMock()
trigger_def = mock.MagicMock()
dist_traits = 'some traits'
event = "eventful!"
ret = tm._add_or_create_stream(trigger_def, event, dist_traits)
tm.db.get_active_stream.assert_called_once_with(trigger_def.name,
dist_traits, tm.current_time.return_value)
self.assertFalse(tm.db.create_stream.called)
tm.db.add_event_stream.assert_called_once_with(
tm.db.get_active_stream.return_value,
event, trigger_def.expiration)
self.assertEqual(ret, tm.db.get_active_stream.return_value)
@mock.patch.object(trigger_manager.ConfigManager, 'wrap')
def test_add_or_create_stream_create(self, mock_config_wrap):
tm = trigger_manager.TriggerManager('test')
tm.db = mock.MagicMock(spec=tm.db)
tm.db.get_active_stream.return_value = None
tm.current_time = mock.MagicMock()
trigger_def = mock.MagicMock()
dist_traits = 'some traits'
event = "eventful!"
ret = tm._add_or_create_stream(trigger_def, event, dist_traits)
tm.db.get_active_stream.assert_called_once_with(trigger_def.name, dist_traits,
tm.current_time.return_value)
tm.db.create_stream.assert_called_once_with(trigger_def.name, event, dist_traits,
trigger_def.expiration)
self.assertFalse(tm.db.add_event_stream.called)
self.assertEqual(ret, tm.db.create_stream.return_value)
@mock.patch.object(trigger_manager.ConfigManager, 'wrap')
def test_ready_to_fire(self, mock_config_wrap):
tm = trigger_manager.TriggerManager('test')
tm.db = mock.MagicMock(spec=tm.db)
tm.current_time = mock.MagicMock()
trigger_def = mock.MagicMock()
test_stream = mock.MagicMock()
tm._ready_to_fire(test_stream, trigger_def)
trigger_def.get_fire_timestamp.assert_called_once_with(tm.current_time.return_value)
tm.db.stream_ready_to_fire.assert_called_once_with(test_stream,
trigger_def.get_fire_timestamp.return_value)
@mock.patch.object(trigger_manager.ConfigManager, 'wrap')
def test_add_notification(self, mock_config_wrap):
tm = trigger_manager.TriggerManager('test')
tm.convert_notification = mock.MagicMock()
tm.add_event = mock.MagicMock()
tm.add_notification("test notification")
tm.convert_notification.assert_called_once_with("test notification")
tm.add_event.assert_called_once_with(tm.convert_notification.return_value)
@mock.patch.object(trigger_manager.ConfigManager, 'wrap')
def test_add_notification_invalid_or_dropped(self, mock_config_wrap):
tm = trigger_manager.TriggerManager('test')
tm.convert_notification = mock.MagicMock()
tm.add_event = mock.MagicMock()
tm.convert_notification.return_value = None
tm.add_notification("test notification")
tm.convert_notification.assert_called_once_with("test notification")
self.assertFalse(tm.add_event.called)
@mock.patch.object(trigger_manager.ConfigManager, 'wrap')
def test_add_event(self, mock_config_wrap):
tm = trigger_manager.TriggerManager('test')
tm.db = mock.MagicMock(spec=tm.db)
tm.trigger_definitions = [mock.MagicMock() for n in range(3)]
for d in tm.trigger_definitions:
d.debugger = self.debugger
m_def = tm.trigger_definitions[2]
tm.trigger_definitions[0].match.return_value = None
tm.trigger_definitions[1].match.return_value = None
event = mock.MagicMock(name='event', spec=dict)
tm.save_event = mock.MagicMock()
tm._add_or_create_stream = mock.MagicMock()
tm._add_or_create_stream.return_value.fire_timestamp = None
tm._ready_to_fire = mock.MagicMock()
m_def.should_fire.return_value = True
tm.add_event(event)
tm.save_event.assert_called_once_with(event)
for td in tm.trigger_definitions:
td.match.assert_called_once_with(event)
m_def.get_distinguishing_traits.assert_called_once_with(event,
m_def.match.return_value)
tm._add_or_create_stream.assert_called_once_with(m_def, event,
m_def.get_distinguishing_traits.return_value)
tm.db.get_stream_events.assert_called_once_with(
tm._add_or_create_stream.return_value)
m_def.should_fire.assert_called_once_with(
tm.db.get_stream_events.return_value)
tm._ready_to_fire.assert_called_once_with(
tm._add_or_create_stream.return_value, m_def)
@mock.patch.object(trigger_manager.ConfigManager, 'wrap')
def test_add_event_on_ready_stream(self, mock_config_wrap):
tm = trigger_manager.TriggerManager('test')
tm.db = mock.MagicMock(spec=tm.db)
tm.trigger_definitions = [mock.MagicMock() for n in range(3)]
m_def = tm.trigger_definitions[2]
tm.trigger_definitions[0].match.return_value = None
tm.trigger_definitions[1].match.return_value = None
event = mock.MagicMock(name='event', spec=dict)
tm.save_event = mock.MagicMock()
tm._add_or_create_stream = mock.MagicMock()
tm._add_or_create_stream.return_value.fire_timestamp = "Fire!"
tm._ready_to_fire = mock.MagicMock()
m_def.should_fire.return_value = True
tm.add_event(event)
tm.save_event.assert_called_once_with(event)
for td in tm.trigger_definitions:
td.match.assert_called_once_with(event)
m_def.get_distinguishing_traits.assert_called_once_with(event,
m_def.match.return_value)
tm._add_or_create_stream.assert_called_once_with(m_def, event,
m_def.get_distinguishing_traits.return_value)
self.assertFalse(tm.db.get_stream_events.called)
self.assertFalse(m_def.should_fire.called)
self.assertFalse(tm._ready_to_fire.called)
@mock.patch.object(trigger_manager.ConfigManager, 'wrap')
def test_add_event_no_match(self, mock_config_wrap):
tm = trigger_manager.TriggerManager('test')
tm.db = mock.MagicMock(spec=tm.db)
tm.trigger_definitions = [mock.MagicMock() for n in range(3)]
tm.trigger_definitions[0].match.return_value = None
tm.trigger_definitions[1].match.return_value = None
tm.trigger_definitions[2].match.return_value = None
event = mock.MagicMock(name='event', spec=dict)
tm.save_event = mock.MagicMock()
tm._add_or_create_stream = mock.MagicMock()
tm._add_or_create_stream.return_value.fire_timestamp = "Fire!"
tm._ready_to_fire = mock.MagicMock()
tm.add_event(event)
tm.save_event.assert_called_once_with(event)
for td in tm.trigger_definitions:
td.match.assert_called_once_with(event)
for td in tm.trigger_definitions:
self.assertFalse(td.get_distinguishing_traits.called)
self.assertFalse(td.should_fire.called)
self.assertFalse(tm._add_or_create_stream.called)
self.assertFalse(tm.db.get_stream_events.called)
self.assertFalse(tm._ready_to_fire.called)