318 lines
14 KiB
Python
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)
|