stacktach-winchester/tests/test_trigger_manager.py

318 lines
14 KiB
Python

# Copyright (c) 2014 Dark Secret Software Inc.
# Copyright (c) 2015 Rackspace
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
# implied.
# See the License for the specific language governing permissions and
# limitations under the License.
import unittest2 as unittest
import mock
import datetime
from winchester import db as winch_db
from winchester import debugging
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.assertEqual(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)
@mock.patch.object(trigger_manager.ConfigManager, 'wrap')
def test_add__del_trigger_definition(self, mock_config_wrap):
tm = trigger_manager.TriggerManager('test')
tm.db = mock.MagicMock(spec=tm.db)
td1 = dict(
name='test_trigger1',
expiration='$last + 1d',
fire_pipeline='test_pipeline',
fire_criteria=[dict(event_type='test.thing')],
match_criteria=[dict(event_type='test.*')])
tdlist = list()
tdlist.append(td1)
tm.add_trigger_definition(tdlist)
self.assertTrue('test_trigger1' in tm.trigger_map)
tm.delete_trigger_definition('test_trigger1')
self.assertFalse('test_trigger1' in tm.trigger_map)