"""Audio validation logic module unit test.""" import json from flexmock import flexmock import pytest from src import audio_validation_logic from src import mediainfo_extractor from src import metadata_validator from src import s3 @pytest.fixture def validate_audio_asset_inputs(): """Input values for validate_audio_asset.""" return { 'bucket': 'test_bucket_name', 'key': 'test_key' } @pytest.fixture def asset_validation_fixture_results(): """Fixture for method results in validate_audio_asset function.""" return { 'create_presigned_url': 'presigned_url', 'get_all_media_info': { 'duration_ms': 2963, 'channels': 2, 'codec': 'pcm', 'bit_rate': 1411200, 'sample_rate': 44100, 'bits_per_sample': 16, 'container': 'wave', 'file_size_bytes': 522796, 'mime_type': 'AUDIO/WAV', 'test_for_removal_of_fields_set_to_none': None, }, 'get_lossless_flag': True, 'validate_audio_metadata': { 'duration_ms': 2963, 'channels': 2, 'codec': 'pcm', 'bit_rate': 1411200, 'sample_rate': 44100, 'bits_per_sample': 16, 'container': 'wave', 'mime_type': 'audio/wav', 'file_size_bytes': 522796, 'lossless': True, }, 'not_audio_metadata': { 'file_size': 12345, } } @pytest.mark.parametrize(( 'test_description', 'metadata_fields_missing_from_mediainfo', 'expected_metadata_fields_missing_from_validation_payload', ), [ ( 'nothing missing', set(), set(), ), ( 'missing mime_type but able to compute it from container', {'mime_type'}, set(), ), ( 'missing mime_type and lossless' 'because of missing mime_type and container', {'mime_type', 'container'}, {'mime_type', 'container', 'lossless'} ), ( 'missing lossless because of missing codec', {'codec'}, {'codec', 'lossless'}, ), ]) def test_validate_audio_asset_success( validate_audio_asset_inputs, asset_validation_fixture_results, test_description, metadata_fields_missing_from_mediainfo, expected_metadata_fields_missing_from_validation_payload, ): """Test for successful call of validate_audio_asset.""" # data preparation expected_result = ( asset_validation_fixture_results['validate_audio_metadata']) # mocking (flexmock(s3) .should_receive('create_presigned_url') .with_args( validate_audio_asset_inputs['bucket'], validate_audio_asset_inputs['key']) .and_return(asset_validation_fixture_results['create_presigned_url']) .once()) (flexmock(mediainfo_extractor) .should_receive('get_audio_asset_media_info') .with_args(asset_validation_fixture_results['create_presigned_url']) .and_return({ key: value for key, value in asset_validation_fixture_results['get_all_media_info'].items() if key not in metadata_fields_missing_from_mediainfo }) .once()) (flexmock(metadata_validator) .should_receive('validate_audio_metadata') .with_args({ key: value for key, value in asset_validation_fixture_results['validate_audio_metadata'].items() if key not in expected_metadata_fields_missing_from_validation_payload }) .and_return(asset_validation_fixture_results['validate_audio_metadata']) .once()) # test functional call result = audio_validation_logic.validate_audio_asset( validate_audio_asset_inputs['bucket'], validate_audio_asset_inputs['key']) # checking assert result == expected_result def test_validate_audio_asset_failure( validate_audio_asset_inputs, asset_validation_fixture_results): """Test for failure call of validate_audio_asset.""" # mocking (flexmock(s3) .should_receive('create_presigned_url') .with_args( validate_audio_asset_inputs['bucket'], validate_audio_asset_inputs['key']) .and_return(asset_validation_fixture_results['create_presigned_url']) .once()) (flexmock(mediainfo_extractor) .should_receive('get_audio_asset_media_info') .with_args(asset_validation_fixture_results['create_presigned_url']) .and_raise(Exception('some error')) .once()) # test functional call with pytest.raises(Exception, match='some error'): audio_validation_logic.validate_audio_asset( validate_audio_asset_inputs['bucket'], validate_audio_asset_inputs['key']) def test_validation_of_non_audio_asset( validate_audio_asset_inputs, asset_validation_fixture_results): """Test non-audio asset call to validate_audio_asset.""" (flexmock(s3) .should_receive('create_presigned_url') .with_args( validate_audio_asset_inputs['bucket'], validate_audio_asset_inputs['key']) .and_return(asset_validation_fixture_results['create_presigned_url']) .once()) (flexmock(mediainfo_extractor) .should_receive('get_audio_asset_media_info') .with_args(asset_validation_fixture_results['create_presigned_url']) .and_return(asset_validation_fixture_results['not_audio_metadata']) .once()) # test functional call with pytest.raises( metadata_validator.InvalidAudioError ) as invalid_audio_error: audio_validation_logic.validate_audio_asset( validate_audio_asset_inputs['bucket'], validate_audio_asset_inputs['key']) # checking assert json.loads(str(invalid_audio_error.value)) == { 'errors': { 'bit_rate': 'is required', 'bits_per_sample': 'is required', 'channels': 'is required', 'codec': 'is required', 'container': 'is required', 'duration_ms': 'is required', 'file_size_bytes': 'is required', 'lossless': 'is required', 'mime_type': 'is required', 'sample_rate': 'is required' }, 'metadata': {'file_size': 12345}, }