"""Lambda test module.""" import datetime import json from copy import deepcopy from unittest.mock import patch import botocore import pytest from src import app as index from src import audio_validator from src.common import lambda_exceptions test_filename = 'test_filename' test_bucket = 'test_bucket' test_presigned_url = 'https://urltoaudio.com' event_mock = { 'key': test_filename, 'bucket': test_bucket, 'file_type': 'test_file_type', 'config': { 'output_bucket_name': 'bucket-name', 'preview_bucket_name': 'bucket-name', 'elastic_transcoder_id': '123' } } @patch('subprocess.check_output') @patch('src.common.s3.client') @patch('src.common.status.client') @patch('src.common.status.datetime') def test_handler_success(datetime_mock, sns_client, s3_client, mediainfo_mock): """Test handler function.""" datetime_mock.datetime.now.return_value = datetime.datetime(2020, 1, 1) s3_client.generate_presigned_url.return_value = test_presigned_url mediainfo_mock.side_effect = [ b'playtime_seconds 24384 * channels 2 * codec PCM * sample_rate 44100 * bits_per_sample 16 * ' b'bit_rate 1411200\n', b'container Wave * mime_type audio/vnd.wave * file_size 4301448\n'] result = index.handler(event_mock, None) assert result == event_mock sns_client.publish.assert_called_with( TopicArn='general-topic-arn', Message=json.dumps({ 'function': 'asset-transcoder-audio-validation', 'status': 'validation_complete', 'filename': 'test_filename', 'bucket': 'test_bucket', 'status_time': '2020-01-01T00:00:00.000000Z' }) ) @patch('src.common.status.client') @patch('src.common.status.datetime') def test_handler_lambda_event_error(datetime_mock, sns_client): """Test handler function with an invalid lambda event.""" datetime_mock.datetime.now.return_value = datetime.datetime(2020, 1, 1) bad_event = deepcopy(event_mock) del bad_event['config']['elastic_transcoder_id'] with pytest.raises(lambda_exceptions.LambdaEventError) as err: index.handler(bad_event, None) assert err.value.error_code == 'lambda_event_error' assert str(err.value) == 'Lambda event from previous step is invalid. {message}'.format( message=json.dumps({'config': {'elastic_transcoder_id': ['Missing data for required field.']}}) ) sns_client.publish.assert_called_with( TopicArn='general-topic-arn', Message=json.dumps({ 'function': 'asset-transcoder-audio-validation', 'status': 'validation_error', 'filename': 'test_filename', 'bucket': 'test_bucket', 'status_time': '2020-01-01T00:00:00.000000Z', 'errors': err.value.errors }) ) @patch('src.common.s3.client') @patch('src.common.status.client') @patch('src.common.status.datetime') def test_handler_object_not_found(datetime_mock, sns_client, s3_client): """Test handler function with an object that does not exist.""" datetime_mock.datetime.now.return_value = datetime.datetime(2020, 1, 1) error = {'Error': {'Code': '404', 'Message': 'Not found'}, 'ResponseMetadata': {'HTTPStatusCode': 404}} s3_client.generate_presigned_url.side_effect = botocore.exceptions.ClientError(error, 'HeadObject') with pytest.raises(lambda_exceptions.S3Error) as err: index.handler(event_mock, None) sns_client.publish.assert_called_with( TopicArn='general-topic-arn', Message=json.dumps({ 'function': 'asset-transcoder-audio-validation', 'status': 'validation_error', 'filename': 'test_filename', 'bucket': 'test_bucket', 'status_time': '2020-01-01T00:00:00.000000Z', 'errors': err.value.errors })) @patch('subprocess.check_output') @patch('src.common.s3.client') @patch('src.common.status.client') @patch('src.common.status.datetime') def test_handler_with_failed_validation(datetime_mock, sns_client, s3_client, mediainfo_mock): """Test handler function.""" datetime_mock.datetime.now.return_value = datetime.datetime(2020, 1, 1) s3_client.generate_presigned_url.return_value = test_presigned_url mediainfo_mock.side_effect = [ b'playtime_seconds 2963 * channels 1 * codec PCM * sample_rate 44100 * bits_per_sample 16 * bit_rate 705600\n', b'container Wave * mime_type audio/vnd.wave * file_size 261420\n' ] with pytest.raises(audio_validator.InvalidAudioError) as err: index.handler(event_mock, None) sns_client.publish.assert_called_with( TopicArn='general-topic-arn', Message=json.dumps({ 'function': 'asset-transcoder-audio-validation', 'status': 'validation_error', 'filename': 'test_filename', 'bucket': 'test_bucket', 'status_time': '2020-01-01T00:00:00.000000Z', 'errors': err.value.errors })) @patch('subprocess.check_output') @patch('src.common.s3.client') @patch('src.common.status.client') @patch('src.common.status.datetime') def test_handler_with_missing_mediainfo_binary(datetime_mock, sns_client, s3_client, mediainfo_mock): """Test handler function.""" datetime_mock.datetime.now.return_value = datetime.datetime(2020, 1, 1) s3_client.generate_presigned_url.return_value = test_presigned_url mediainfo_mock.return_value = None with pytest.raises(RuntimeError) as err: index.handler(event_mock, None) errors = { 'audio_validation_error': 'An error occurred during the audio validation. Error message: {}'.format(str(err.value))} sns_client.publish.assert_called_with( TopicArn='general-topic-arn', Message=json.dumps({ 'function': 'asset-transcoder-audio-validation', 'status': 'validation_error', 'filename': 'test_filename', 'bucket': 'test_bucket', 'status_time': '2020-01-01T00:00:00.000000Z', 'errors': errors })) @patch('subprocess.check_output') @patch('src.common.s3.client') @patch('src.common.status.client') @patch('src.common.status.datetime') def test_handler_with_missing_mediainfo_empty_output(datetime_mock, sns_client, s3_client, mediainfo_mock): """Test handler function.""" datetime_mock.datetime.now.return_value = datetime.datetime(2020, 1, 1) s3_client.generate_presigned_url.return_value = test_presigned_url with pytest.raises(KeyError) as err: index.handler(event_mock, None) errors = { 'audio_validation_error': 'An error occurred during the audio validation. Error message: {}'.format(str(err.value))} sns_client.publish.assert_called_with( TopicArn='general-topic-arn', Message=json.dumps({ 'function': 'asset-transcoder-audio-validation', 'status': 'validation_error', 'filename': 'test_filename', 'bucket': 'test_bucket', 'status_time': '2020-01-01T00:00:00.000000Z', 'errors': errors }))