"""Test module image/audion/general metadata extraction functions.""" from unittest.mock import patch import pytest from lambdacommon import common_config from lambdacommon import mediainfo_extractor from lambdacommon.constants import mediainfo_const mock_file_path = 'some/file/path.general' @pytest.fixture def valid_binary_audio_asset_processing_result(): """Return valid audio asset mediainfo cli result in binary string.""" return ( b'playtime_seconds 2963 * channels 2 * codec PCM * bit_rate 1411200 * ' b'sample_rate 44100 * resolution 16 * bits_per_sample 24' ) @pytest.fixture def valid_binary_audio_asset_processing_result_with_duration_ratio(): """Return valid audio asset mediainfo cli result in binary string.""" return ( b'playtime_seconds 2963 / 2742 * channels 2 * codec PCM * bit_rate 1411200 * ' b'sample_rate 44100 * resolution 16 * bits_per_sample 24' ) @pytest.fixture def valid_binary_image_asset_processing_result(): """Return valid image asset mediainfo cli result in binary string.""" return b'width 3000 * height 4000' @pytest.fixture def valid_binary_general_processing_result(): """Return valid asset general mediainfo cli result in binary string.""" return b'container JPEG * mime_type image/jpeg * file_size 977851' @pytest.fixture def get_media_info_audio(): """Return expected audio info.""" return { 'playtime_seconds': 2963, 'channels': 2, 'codec': 'pcm', 'bit_rate': 1411200, 'sample_rate': 44100, 'bits_per_sample': 24, 'resolution': 16 } @pytest.fixture def get_media_info_image(): """Return expected image info.""" return { 'height': 4000, 'width': 3000 } @pytest.fixture def get_media_info_general(): """Return expected general info.""" return { 'container': 'jpeg', 'mime_type': 'image/jpeg', 'file_size': 977851 } @patch('subprocess.check_output') def test_get_media_info_audio_info(subprocess_mock, valid_binary_audio_asset_processing_result, get_media_info_audio): """Test for successful parsing of audio info.""" subprocess_mock.return_value = valid_binary_audio_asset_processing_result result = mediainfo_extractor.get_media_info(mock_file_path, mediainfo_const.AUDIO_INFO_PARAM_FILTER) assert result == get_media_info_audio subprocess_mock.assert_called_with([ common_config.MEDIAINFO_PATH, mediainfo_const.AUDIO_INFO_PARAM_FILTER, mock_file_path]) @patch('subprocess.check_output') def test_get_media_info_audio_info_with_duration_ratio( subprocess_mock, valid_binary_audio_asset_processing_result_with_duration_ratio, get_media_info_audio): """Test for successful parsing of audio info.""" subprocess_mock.return_value = valid_binary_audio_asset_processing_result_with_duration_ratio result = mediainfo_extractor.get_media_info(mock_file_path, mediainfo_const.AUDIO_INFO_PARAM_FILTER) assert result == get_media_info_audio subprocess_mock.assert_called_with([ common_config.MEDIAINFO_PATH, mediainfo_const.AUDIO_INFO_PARAM_FILTER, mock_file_path]) @patch('subprocess.check_output') def test_get_media_info_image_info( subprocess_mock, valid_binary_image_asset_processing_result, get_media_info_image): """Test for successful parsing of image info.""" subprocess_mock.return_value = valid_binary_image_asset_processing_result result = mediainfo_extractor.get_media_info(mock_file_path, mediainfo_const.IMAGE_INFO_PARAM_FILTER) assert result == get_media_info_image subprocess_mock.asert_called_with([ common_config.MEDIAINFO_PATH, mediainfo_const.IMAGE_INFO_PARAM_FILTER, mock_file_path]) @patch('subprocess.check_output') def test_get_media_info_general_info( subprocess_mock, valid_binary_general_processing_result, get_media_info_general): """Test for successful parsing of image info.""" subprocess_mock.return_value = valid_binary_general_processing_result result = mediainfo_extractor.get_media_info( mock_file_path, mediainfo_const.GENERAL_INFO_PARAM_FILTER) assert result == get_media_info_general subprocess_mock.assert_called_with([ common_config.MEDIAINFO_PATH, mediainfo_const.GENERAL_INFO_PARAM_FILTER, mock_file_path]) @patch('subprocess.check_output') def test_get_media_info_subprocess_failure(subprocess_mock): """Test get_media_info failure during subprocess call.""" mock_error_message = 'error' subprocess_mock.side_effect = OSError(mock_error_message) with pytest.raises(OSError) as e: mediainfo_extractor.get_media_info(mock_file_path, mediainfo_const.CLI_FILTERS[0]) subprocess_mock.assert_called_once_with([ common_config.MEDIAINFO_PATH, mediainfo_const.CLI_FILTERS[0], mock_file_path]) assert str(e) == mock_error_message @pytest.fixture def valid_audio_mediainfo_output(): """Get valid data from call of mediainfo cli.""" return { 'processed': { 'playtime_seconds': 246842, 'channels': 2, 'codec': 'pcm', 'bit_rate': 1411200, 'sample_rate': 44100, 'bits_per_sample': 16, 'container': 'wave' }, 'source': { 'playtime_seconds': '246842', 'channels': '2', 'codec': 'pcm', 'bit_rate': '1411200', 'sample_rate': '44100', 'bits_per_sample': '16', 'container': 'Wave', 'file_size': '324234234', 'mime_type': 'audio/wave' } } @pytest.mark.parametrize('key, expected_type', [ ('playtime_seconds', int), ('channels', int), ('codec', str), ('bit_rate', int), ('sample_rate', int), ('bits_per_sample', int), ('container', str), ('file_size', int), ('mime_type', str), ]) def test_type_cast(key, expected_type, valid_audio_mediainfo_output): """Test for success of type_cast.""" string_value = valid_audio_mediainfo_output['source'][key] result = mediainfo_extractor.type_cast(key, string_value) assert type(result) == expected_type def test_type_cast_empty_string(): """Test for success of type_cast of an empty string.""" result = mediainfo_extractor.type_cast('bits_per_sample', '') assert result == 0