''' Unit test definitions for all rules ''' import mailer import pytest from alertaclient.models.alert import Alert from mock import DEFAULT, MagicMock, patch def test_rules_dont_exist(): ''' Test the rules file is read ''' with patch('mailer.os') as system_os: system_os.path.exists.return_value = False # res = mailer.parse_group_rules('config_file') system_os.path.exists.called_once_with('confile_file') # assert res is None def test_rules_parsing(): ''' Test the rules file is properly read ''' with patch.multiple(mailer, os=DEFAULT, open=DEFAULT, json=DEFAULT, validate_rules=DEFAULT) as mocks: mocks['os'].path.exists.return_value = True mocks['os'].walk().__iter__\ .return_value = [('/', None, ['cantopen.json', 'invalid.json', 'valid.json'])] invalid_file = MagicMock() valid_file = MagicMock() mocks['open'].side_effect = [IOError, invalid_file, valid_file] doc = [{'notify': {'fields': []}}] mocks['json'].load.side_effect = [TypeError, doc] mocks['validate_rules'].return_value = doc res = mailer.parse_group_rules('config_file') # Assert that we checked for folder existence mocks['os'].path.exists.called_once_with('confile_file') # Check that validation was called for valid file mocks['validate_rules'].assert_called_once_with(doc) assert mocks['validate_rules'].call_count == 1 # Assert that we tried to open all 3 files assert mocks['open'].call_count == 3 # Assert that we tried to load 2 files only assert mocks['json'].load.call_count == 2 # Assert that we have proper return value assert res == doc TESTDOCS = [ ('', False), ('String', False), ({}, False), ([], True), ([ {'name': 'invalid_no_fields', 'contacts': []} ], False), ([ {'name': 'invalid_empty_fields', 'fields': [], 'contacts': []} ], False), ([ {'name': 'invalid_no_contacts', 'fields': [{'field': 'resource', 'regex': r'\d{4}'}]} ], False), ([ {'name': 'invalid_no_field_on_fields', 'fields': [{'regex': r'\d{4}'}], 'contacts': []} ], False), ([ {'name': 'invalid_fields_not_list', 'fields': {'regex': r'\d{4}'}, 'contacts': []} ], False), ([ {'name': 'invalid_no_fields_regex', 'fields': [{'field': 'test'}], 'contacts': []} ], False), ([ {'name': 'invalid_no_fields_regex', 'fields': [{'field': 'tags', 'regex': 'atag'}], 'exclude': True, 'contacts': []} ], True), ] @pytest.mark.parametrize('doc, is_valid', TESTDOCS) def test_rules_validation(doc, is_valid): ''' Test rule validation ''' res = mailer.validate_rules(doc) if is_valid: assert res is not None and res == doc else: assert res is None or res == [] RULES_DATA = [ # ({'resource': 'server-1234', 'event': '5678'}, [], []), ({'resource': '1234', 'event': '5678'}, [{'name': 'Test1', 'fields': [{'field': 'resource', 'regex': r'(\w.*)?\d{4}'}], 'contacts': ['test@example.com']}], ['test@example.com']) ] @pytest.mark.parametrize('alert_spec, input_rules, expected_contacts', RULES_DATA) def test_rules_evaluation(alert_spec, input_rules, expected_contacts): ''' Test that rules are properly evaluated ''' with patch.dict(mailer.OPTIONS, mailer.DEFAULT_OPTIONS): mailer.OPTIONS['mail_to'] = [] mailer.OPTIONS['group_rules'] = input_rules mail_sender = mailer.MailSender() with patch.object(mail_sender, '_send_email_message') as _sem: alert = Alert.parse(alert_spec) _, emailed_contacts = mail_sender.send_email(alert) assert _sem.call_count == 1 assert emailed_contacts == expected_contacts def test_rule_matches_list(): ''' Test regex matching is working properly for a list ''' # Mock options to instantiate mailer with patch.dict(mailer.OPTIONS, mailer.DEFAULT_OPTIONS): mail_sender = mailer.MailSender() with patch.object(mailer, 're') as regex: regex.match.side_effect = [MagicMock(), None] assert mail_sender._rule_matches('regex', ['item1']) is True regex.match.assert_called_with('regex', 'item1') assert mail_sender._rule_matches('regex', ['item2']) is False regex.match.assert_called_with('regex', 'item2') def test_rule_matches_string(): ''' Test regex matching is working properly for a string ''' # Mock options to instantiate mailer with patch.dict(mailer.OPTIONS, mailer.DEFAULT_OPTIONS): mail_sender = mailer.MailSender() with patch.object(mailer, 're') as regex: regex.search.side_effect = [MagicMock(), None] assert mail_sender._rule_matches('regex', 'value1') is True regex.search.assert_called_with('regex', 'value1') assert mail_sender._rule_matches('regex', 'value2') is False regex.search.assert_called_with('regex', 'value2')