"""Test module audio metadata extraction functions.""" import subprocess from unittest.mock import MagicMock from unittest.mock import patch from flexmock import flexmock import pytest from transcoding import config from transcoding.constants import error from transcoding.constants import mediainfo as mediainfo_const from transcoding.utils import mediainfo_extractor @pytest.fixture def valid_binary_mediainfo_wav_or_flac_processing_result(): """Get valid mediainfo cli wav or flac result in binary string.""" return (b'{"media": ' b'{"track": [{},{"Duration": "246.842", "Channels": "2", "SamplingRate": "44100", "BitDepth": "24"}]}}') @pytest.fixture def valid_binary_mediainfo_mp3_processing_result(): """Get valid mediainfo cli mp3 result in binary string.""" return (b'{"media": ' b'{"track": [{},{"Duration": "15.047", "Channels": "2", "SamplingRate": "44100", "BitDepth": ""}]}}') @pytest.fixture def invalid_binary_mediainfo_processing_result(): """Get invalid mediainfo cli result in binary string.""" return b'duration_ms not_an_int * channels not_an_int * sample_rate not_an_int * bits_per_sample not_an_int' def test_get_media_info_wav_or_flac_success(valid_binary_mediainfo_wav_or_flac_processing_result): """Test for success of get_media_info with wav or flac file.""" mock_file_path = '/mock_path' pipe_mock = MagicMock() pipe_mock.communicate.return_value = ( valid_binary_mediainfo_wav_or_flac_processing_result, b'') (flexmock(subprocess) .should_receive('Popen') .with_args( [config.MEDIAINFO_PATH, mediainfo_const.AUDIO_INFO_PARAM_FILTER, mock_file_path], stdout=subprocess.PIPE, stderr=subprocess.PIPE) .and_return(pipe_mock)) response = mediainfo_extractor.get_media_info( mock_file_path, mediainfo_const.AUDIO_INFO_PARAM_FILTER) assert response assert response.status == 200 assert response.message == { 'BitDepth': '24', 'Channels': '2', 'Duration': '246.842', 'SamplingRate': '44100', } def test_get_media_info_mp3_success(valid_binary_mediainfo_mp3_processing_result): """Test for success of get_media_info with mp3 file.""" mock_file_path = '/mock_path' pipe_mock = MagicMock() pipe_mock.communicate.return_value = ( valid_binary_mediainfo_mp3_processing_result, b'') (flexmock(subprocess) .should_receive('Popen') .with_args( [config.MEDIAINFO_PATH, mediainfo_const.AUDIO_INFO_PARAM_FILTER, mock_file_path], stdout=subprocess.PIPE, stderr=subprocess.PIPE) .and_return(pipe_mock)) response = mediainfo_extractor.get_media_info( mock_file_path, mediainfo_const.AUDIO_INFO_PARAM_FILTER) assert response assert response.status == 200 assert response.message == { 'BitDepth': '', 'Channels': '2', 'Duration': '15.047', 'SamplingRate': '44100', } def test_get_media_info_mediainfo_output_failure(): """Test get_media_info failure for empty mediainfo output.""" mock_file_path = '/mock_path' std_error_message = b'/mock_path' expected_error = error.ERROR_MESSAGE_INVALID_AUDIO_ASSET.format( asset_path=std_error_message.decode()) pipe_mock = MagicMock() pipe_mock.communicate.return_value = (b'', std_error_message) (flexmock(subprocess) .should_receive('Popen') .with_args( [config.MEDIAINFO_PATH, mediainfo_const.AUDIO_INFO_PARAM_FILTER, mock_file_path], stdout=subprocess.PIPE, stderr=subprocess.PIPE) .and_return(pipe_mock)) response = mediainfo_extractor.get_media_info( mock_file_path, mediainfo_const.AUDIO_INFO_PARAM_FILTER) assert not response assert response.status == 400 assert response.errors['message'] == expected_error @patch('subprocess.Popen') def test_get_media_info_subprocess_failure(subprocess_mock): """Test get_media_info failure during subprocess call.""" mock_file_path = '/mock_path' mock_error_message = 'error' subprocess_mock.side_effect = OSError(mock_error_message) response = mediainfo_extractor.get_media_info( mock_file_path, mediainfo_const.AUDIO_INFO_PARAM_FILTER) subprocess_mock.assert_called_once_with( [config.MEDIAINFO_PATH, mediainfo_const.AUDIO_INFO_PARAM_FILTER, mock_file_path], stdout=subprocess.PIPE, stderr=subprocess.PIPE) assert not response assert response.status == 500 assert response.errors['message'] == mock_error_message def test_get_media_info_failure_invalid_file( invalid_binary_mediainfo_processing_result): """Test for failure of get_media_info function call.""" mock_file_path = '/mock_path' expected_error_message = error.ERROR_MESSAGE_INVALID_AUDIO_ASSET.format( asset_path=mock_file_path) pipe_mock = MagicMock() pipe_mock.communicate.return_value = ( invalid_binary_mediainfo_processing_result, b'') (flexmock(subprocess) .should_receive('Popen') .with_args( [config.MEDIAINFO_PATH, mediainfo_const.AUDIO_INFO_PARAM_FILTER, mock_file_path], stdout=subprocess.PIPE, stderr=subprocess.PIPE) .and_return(pipe_mock)) response = mediainfo_extractor.get_media_info( mock_file_path, mediainfo_const.AUDIO_INFO_PARAM_FILTER) assert not response assert response.status == 400 assert response.errors['message'] == expected_error_message