"""Test core function handler.""" import importlib from unittest import mock import config import pytest from requests.exceptions import HTTPError from src import app from src.common.connectors import s3_assets @mock.patch('src.app.s3_assets') @mock.patch('src.app.ows_sound_recordings') @mock.patch('src.app.ACRCloudClient', autospec=True) @mock.patch( 'config.ACR_CLOUD_BUCKET_ID', new_callable=mock.PropertyMock(return_value='456') ) @mock.patch( 'src.app.ACR_CLOUD_ACCESS_TOKEN', new_callable=mock.PropertyMock(return_value='acr-cloud-token') ) @mock.patch( 'config.ACR_CLOUD_MAX_FINGERPRINT_SIZE', new_callable=mock.PropertyMock(return_value=17) ) def test_handler( mock_size, mock_token, mock_bucket_id, mock_acr, mock_ows, mock_read_s3): """Test handler method calls.""" mock_acr_client = mock_acr.return_value mock_acr_client.upload_fingerprint.return_value = 'acrid-123' mock_read_s3.download_asset.return_value = b'music' mock_ows.post_acrid.return_value = [999] test_event = { 'asset': { 'id': '123', 'filename': 'abc', 'extension': 'wav' } } result = app.handler(test_event, None) assert mock_acr.call_args_list == [ mock.call( 'acr-cloud-token', config.ACR_CLOUD_URL, max_fingerprint_size=17 ) ] assert mock_read_s3.download_asset.call_args_list == [ mock.call('abc', 'wav') ] assert mock_acr_client.upload_fingerprint.call_args_list == [ mock.call('456', '123', b'music') ] assert mock_ows.post_acrid.call_args_list == [ mock.call('123', 'acrid-123') ] assert result == { 'track_ids': [999] } @mock.patch('src.app.s3_assets') @mock.patch('src.app.logger', autospec=True) def test_file_size_exception(mock_logger, mock_s3): """Test file too large is logger and uncaught.""" mock_s3.download_asset.side_effect = s3_assets.FileTooLarge() test_event = { 'asset': { 'id': '123', 'filename': 'abc', 'extension': 'wav' } } with pytest.raises(s3_assets.FileTooLarge): app.handler(test_event, None) assert mock_logger.exception.called @mock.patch('src.app.s3_assets') @mock.patch('src.app.logger', autospec=True) @mock.patch('src.app.ACRCloudClient', autospec=True) def test_acr_exception(mock_acr, mock_logger, mock_s3): """Test HTTP ACR Cloud error are logged.""" mock_acr_client = mock_acr.return_value mock_acr_client.upload_fingerprint.side_effect = HTTPError('error') test_event = { 'asset': { 'id': '123', 'filename': 'abc', 'extension': 'wav' } } with pytest.raises(HTTPError): app.handler(test_event, None) assert mock_logger.exception.called assert mock_logger.exception.call_args_list == [ mock.call('error') ] @mock.patch('boto3.client') def test_s3_call(mock_boto): """Test s3 read data calls.""" mock_client = mock_boto.return_value mock_get_object = mock_client.get_object mock_get_object.return_value['Body'].read.return_value = b'music' result = app._read_s3_object('bucket-123', 'key-456') assert mock_boto.called assert mock_boto.call_args_list == [mock.call('s3')] assert mock_get_object.called assert mock_get_object.call_args_list == [ mock.call(Bucket='bucket-123', Key='key-456') ] assert result == b'music' @mock.patch('config.secrets_manager_client') @mock.patch('sentry_sdk.init') def test_handler_init(mock_sentry, mock_secrets): """Test sentry init with dsn.""" mock_secret_values = { 'SENTRY_DSN': 'fake-dsn', 'ACR_CLOUD_ACCESS_TOKEN': 'acr-cloud-token' } mock_secrets.get_cred.side_effect = lambda x: mock_secret_values[x] assert not mock_sentry.called importlib.reload(app) assert mock_sentry.called assert mock_secrets.get_cred.call_args_list == [ mock.call('SENTRY_DSN'), mock.call('ACR_CLOUD_ACCESS_TOKEN') ] assert app.ACR_CLOUD_ACCESS_TOKEN == 'acr-cloud-token' @mock.patch('config.secrets_manager_client') @mock.patch('sentry_sdk.init') def test_handler_init_empty_sentry(mock_sentry, mock_secrets): """Test sentry init with dsn.""" mock_secret_values = { 'SENTRY_DSN': '', 'ACR_CLOUD_ACCESS_TOKEN': 'acr-cloud-token' } mock_secrets.get_cred.side_effect = lambda x: mock_secret_values[x] assert not mock_sentry.called importlib.reload(app) assert not mock_sentry.called @mock.patch('config.secrets_manager_client') @mock.patch('sentry_sdk.init') def test_handler_init_none_sentry(mock_sentry, mock_secrets): """Test sentry init with dsn.""" mock_secret_values = { 'SENTRY_DSN': None, 'ACR_CLOUD_ACCESS_TOKEN': 'acr-cloud-token' } mock_secrets.get_cred.side_effect = lambda x: mock_secret_values[x] assert not mock_sentry.called importlib.reload(app) assert not mock_sentry.called