"""Test message validator.""" import datetime from unittest.mock import Mock import pytest from cache_manager import message_validator from cache_manager import response @pytest.mark.parametrize(', '.join([ 'message', 'valid_md5', 'valid_payload', 'valid_md5_called', 'valid_payload_called', 'validation_error']), [ # Invalid: empty body (Mock(body=''), False, False, False, False, 'empty body'), # Invalid: MD5 mismatch (Mock(body='a'), False, False, True, False, 'MD5 mismatch'), # Invalid: invalid payload (Mock(body='b'), True, False, True, True, 'invalid payload'), # Valid (Mock(body='c'), True, True, True, True, None)]) def test_validate_message( message, valid_md5, valid_payload, valid_md5_called, valid_payload_called, validation_error, monkeypatch): """Test validate_message with params. The matrix above corresponds to the various scenarios. Args: message (Mock): mock of a sqs.Message object. valid_md5 (boolean): whether or not MD5 for the message body is valid. valid_payload (boolean): whether or not message payload is valid. valid_md5_called (boolean): whether or not validate_body_md5 got called. valid_payload_called (boolean): whether or not validate_payload got called. validation_error (str): validation error message. monkeypatch (pytest.monkeypatch): monkeypatch fixture. """ is_valid = bool(message.body and valid_md5 and valid_payload) # Mocking if is_valid: # response.Response class validation_response = Mock( status=response.OK, __bool__=Mock(return_value=is_valid) ) validation_response_mock = Mock(return_value=validation_response) monkeypatch.setattr( message_validator.response, 'Response', validation_response_mock) else: # response.create_validation_error_response function validation_response = Mock( message='Some error happened', error=Exception(validation_error), status=response.ERROR, __bool__=Mock(return_value=is_valid)) validation_response_mock = Mock(return_value=validation_response) monkeypatch.setattr( message_validator.response, 'create_validation_error_response', validation_response_mock) # message_validator.validate_body_md5 function validate_body_md5_mock = Mock(return_value=valid_md5) monkeypatch.setattr(message_validator, 'validate_body_md5', validate_body_md5_mock) # message_validator.validate_payload function validate_payload_mock = Mock(return_value=valid_payload) monkeypatch.setattr(message_validator, 'validate_payload', validate_payload_mock) result = message_validator.validate_message(message) # Asserts assert validation_response_mock.called assert bool(result) == is_valid assert result.status == validation_response.status assert validate_body_md5_mock.called == valid_md5_called assert validate_payload_mock.called == valid_payload_called @pytest.mark.parametrize(', '.join([ 'message', 'valid_keys', 'valid_values,', 'valid_keys_called', 'valid_values_called', 'expected']), [ (Mock(body='{"invalid json'), False, False, False, False, False), (Mock(body='{"valid": "json"}'), False, False, True, False, False), (Mock(body='{"valid": "json"}'), True, False, True, True, False), (Mock(body='{"valid": "json"}'), True, True, True, True, True)]) def test_validate_payload( message, valid_keys, valid_values, valid_keys_called, valid_values_called, expected, monkeypatch): """Test validate_payload with params. Args: message (Mock): mock of a sqs.Message object valid_keys (boolean): whether or not the payload keys are valid. valid_values (boolean): whether or not the payload values are valid. valid_keys_called (boolean): whether or not validate_payload_keys. got called. valid_values_called (boolean): whether or not validate_payload_values got called. expected (boolean): expected result. monkeypatch (pytest.monkeypatch): monkeypatch fixture. """ # Mocking # message_validator.validate_payload_keys function validate_payload_keys_mock = Mock(return_value=valid_keys) monkeypatch.setattr(message_validator, 'validate_payload_keys', validate_payload_keys_mock) # message_validator.validate_payload_values function validate_payload_values_mock = Mock(return_value=valid_values) monkeypatch.setattr(message_validator, 'validate_payload_values', validate_payload_values_mock) actual = message_validator.validate_payload(message) # Asserts assert actual == expected assert validate_payload_keys_mock.called == valid_keys_called assert validate_payload_values_mock.called == valid_values_called @pytest.mark.parametrize('message_body, message_body_md5, expected', [ ('Somebody', 'This is not a valid MD5...', False), ('Somebody', '9b7f4ec82b3352a4a5aba8c7f7957d3e', True)]) def test_validate_body_md5(message_body, message_body_md5, expected): """Test validate_payload with params. Args: message_body (str): actual message body. message_body_md5 (boolean): actual md5 of message body. expected (boolean): expected result. """ # Mock for message message = Mock(body=message_body, md5_of_body=message_body_md5) # Asserts assert message_validator.validate_body_md5(message) == expected @pytest.mark.parametrize('date_str, expected', [ ('2015-08-24', datetime.datetime(2015, 8, 24)), ('111_invalid', False)]) def test_validate_date(date_str, expected): """Test validate_date with params. Args: date_str (str): actual message body. expected (boolean): expected result. """ # Asserts assert message_validator.validate_date(date_str) == expected @pytest.mark.parametrize('payload, expected', [ (dict(key_1='bla', key_2='bla'), True), (dict(key_1='hey', invalid='uhoh'), False)]) def test_validate_payload_keys(payload, expected, monkeypatch): """Test validate_payload_keys with params. Args: payload (dict): message payload. expected (boolean): expected result. monkeypatch (pytest.monkeypatch): monkeypatch fixture. """ monkeypatch.setattr(message_validator, 'PAYLOAD_KEYS', ['key_1', 'key_2']) # Asserts assert message_validator.validate_payload_keys(payload) == expected validate_values_params = [ # Invalid payload: invalid date_start (dict(date_start='invalid'), False, False, False), # Invalid payload: invalid date_end (dict(date_start='2007-08-28', date_end='invalid'), datetime.datetime(2007, 8, 28), False, False), # Invalid payload: date_start > date_end (dict(date_start='2007-08-28', date_end='2007-08-01'), datetime.datetime(2007, 8, 28), datetime.datetime(2007, 8, 1), False), # Invalid payload: no action (dict(date_start='2007-08-28', date_end='2007-08-29'), datetime.datetime(2007, 8, 28), datetime.datetime(2007, 8, 29), False), # Invalid payload: no source (dict(date_start='2007-08-28', date_end='2007-08-29', action='do-stuff'), datetime.datetime(2007, 8, 28), datetime.datetime(2007, 8, 29), False), # Invalid payload: no upcs (dict(date_start='2007-08-28', date_end='2007-08-29', action='do-stuff', source='test'), datetime.datetime(2007, 8, 28), datetime.datetime(2007, 8, 29), False), # Invalid payload: invalid upcs (dict(date_start='2007-08-28', date_end='2007-08-29', action='do-stuff', source='test', upcs='888446987455'), datetime.datetime(2007, 8, 28), datetime.datetime(2007, 8, 29), False), # Invalid payload: no correlation-id (dict(date_start='2007-08-28', date_end='2007-08-29', action='do-stuff', source='test', upcs=['888446987455']), datetime.datetime(2007, 8, 28), datetime.datetime(2007, 8, 29), False), # Valid payload (dict(date_start='2007-08-28', date_end='2007-08-29', action='do-stuff', source='test', upcs=['888446987455'], correlation_id='123456789'), datetime.datetime(2007, 8, 28), datetime.datetime(2007, 8, 29), True) ] @pytest.mark.parametrize(', '.join([ 'payload', 'valid_date_start', 'valid_date_end', 'expected']), validate_values_params) def test_validate_payload_values( payload, valid_date_start, valid_date_end, expected, monkeypatch): """Test validate_payload_values with params. Args: payload (dict): message payload. valid_date_start (bool or datetime.datetime): datetime object if valid, False otherwise. valid_date_end (bool or datetime.datetime): datetime object if valid, False otherwise. expected (boolean): expected result. monkeypatch (pytest.monkeypatch): monkeypatch fixture. """ # Mocking message_validator.validate_payload_values function validate_date_mock = Mock(side_effect=[valid_date_start, valid_date_end]) monkeypatch.setattr(message_validator, 'validate_date', validate_date_mock) # Asserts assert message_validator.validate_payload_values(payload) == expected if (valid_date_start): assert validate_date_mock.call_count is 2 else: assert validate_date_mock.call_count is 1