"""Tests for transcoding order logic.""" from typing import Any import pytest from flexmock import flexmock from owsresponse import response from transcoding.constants import transcoding from transcoding.logic import transcoding_job, transcoding_order from transcoding.models import ( transcoding_job as transcoding_job_model, transcoding_order as transcoding_order_model, ) @pytest.fixture def fixture_transcoding_order() -> dict[str, Any]: """Fixture for transcoding order.""" return { "transcoding_order_id": 6, "input_bucket": "transcoding_input_bucket", "input_key": "transcoding_input_filename", "preset_id": None, "sns_topic": None, "status": transcoding.REQUESTED_STATUS, } @pytest.fixture def fixture_transcoding_jobs_entries() -> list[dict[str, Any]]: """Fixture for transcoding job entries.""" return [ { "transcoding_job_id": 10, "transcoding_order_id": 6, "status": "completed", "description": "", "output_bucket": "ows-transcoding-raw", "output_key": "4e6e4670-03f4-4a34-8d92-123123dc.wav", "container": "wave", "channels": 2, "codec": "pcm", "sample_rate": 44100, "bit_rate": 1411200, "bit_depth": 16, "preset_id": None, "duration": 10000, }, { "transcoding_job_id": 11, "transcoding_order_id": 6, "status": "completed", "description": "", "output_bucket": "ows-transcoding-raw", "output_key": "4e6e4670-03f4-4a34-8d92-123123dc.flac", "container": "flac", "channels": 2, "codec": "flac", "sample_rate": 44100, "bit_rate": 1411200, "bit_depth": 24, "preset_id": None, "duration": 11000, }, ] @pytest.fixture def simplified_transcoding_jobs_fixture() -> list[dict[str, Any]]: """Fixture for simplified transcoding jobs.""" return [ { "status": "completed", "transcoding_job_id": 10, "description": "", "output_bucket": "ows-transcoding-raw", "output_key": "4e6e4670-03f4-4a34-8d92-123123dc.wav", "container": "wave", "duration": 10000, "channels": 2, "codec": "pcm", "sample_rate": 44100, "bit_rate": 1411200, "bit_depth": 16, }, { "status": "completed", "transcoding_job_id": 11, "description": "", "output_bucket": "ows-transcoding-raw", "output_key": "4e6e4670-03f4-4a34-8d92-123123dc.flac", "container": "flac", "duration": 11000, "channels": 2, "codec": "flac", "sample_rate": 44100, "bit_rate": 1411200, "bit_depth": 24, }, ] @pytest.fixture def get_status_mocked_responses( fixture_transcoding_order: dict[str, Any], fixture_transcoding_jobs_entries: list[dict[str, Any]], simplified_transcoding_jobs_fixture: list[dict[str, Any]], ) -> dict[str, Any]: """Fixtures for responses in get_status function.""" return { "transcoding_order": response.Response(fixture_transcoding_order), "transcoding_jobs": response.Response(fixture_transcoding_jobs_entries), "expected_result": { "status": "completed", "transcoding_order_id": 6, "transcoding_jobs": simplified_transcoding_jobs_fixture, }, } @pytest.fixture def fixture_transcoding_rules() -> list[dict[str, Any]]: """Fixture for transcoding rules.""" return [ { "container": "m4a", "channels": 4, "codec": "PCM", "sample_rate": 44100, "bit_rate": 1411200, "bit_depth": 16, }, { "container": "wav", "channels": 2, "codec": "PCM", "sample_rate": 44100, "bit_rate": None, "bit_depth": 32, }, ] def test_create( fixture_transcoding_order: dict[str, Any], fixture_transcoding_rules: list[dict[str, Any]], ) -> None: """Test transcoding order creation.""" expected_output_bucket = "output_bucket" ( flexmock(transcoding_order_model) .should_receive("create_transcoding_order") .with_args( fixture_transcoding_order["input_bucket"], fixture_transcoding_order["input_key"], fixture_transcoding_order["sns_topic"], fixture_transcoding_order["preset_id"], ) .and_return(response.Response(fixture_transcoding_order)) .once() ) ( flexmock(transcoding_job) .should_receive("create") .with_args( fixture_transcoding_order, expected_output_bucket, fixture_transcoding_rules[0], ) .and_return(response.Response("ok")) .once() ) ( flexmock(transcoding_job) .should_receive("create") .with_args( fixture_transcoding_order, expected_output_bucket, fixture_transcoding_rules[1], ) .and_return(response.Response("ok")) .once() ) result = transcoding_order.create( fixture_transcoding_order["input_bucket"], fixture_transcoding_order["input_key"], expected_output_bucket, fixture_transcoding_rules, ) assert result assert ( result.message["transcoding_order_id"] == fixture_transcoding_order["transcoding_order_id"] ) assert result.message["status"] == fixture_transcoding_order["status"] def test_create_with_model_error( fixture_transcoding_order: dict[str, Any], fixture_transcoding_rules: list[dict[str, Any]], ) -> None: """Test transcoding order creation with model error.""" expected_output_bucket = "output_bucket" ( flexmock(transcoding_order_model) .should_receive("create_transcoding_order") .with_args( fixture_transcoding_order["input_bucket"], fixture_transcoding_order["input_key"], fixture_transcoding_order["sns_topic"], fixture_transcoding_order["preset_id"], ) .and_return(response.create_fatal_response("error")) .once() ) result = transcoding_order.create( fixture_transcoding_order["input_bucket"], fixture_transcoding_order["input_key"], expected_output_bucket, fixture_transcoding_rules, ) assert not result assert result.status == 500 def test_create_with_job_error( fixture_transcoding_order: dict[str, Any], fixture_transcoding_rules: list[dict[str, Any]], ) -> None: """Test transcoding order creation with job logic error.""" expected_output_bucket = "output_bucket" ( flexmock(transcoding_order_model) .should_receive("create_transcoding_order") .with_args( fixture_transcoding_order["input_bucket"], fixture_transcoding_order["input_key"], fixture_transcoding_order["sns_topic"], fixture_transcoding_order["preset_id"], ) .and_return(response.Response(fixture_transcoding_order)) .once() ) ( flexmock(transcoding_job) .should_receive("create") .with_args( fixture_transcoding_order, expected_output_bucket, fixture_transcoding_rules[0], ) .and_return(response.create_fatal_response("error")) .once() ) result = transcoding_order.create( fixture_transcoding_order["input_bucket"], fixture_transcoding_order["input_key"], expected_output_bucket, fixture_transcoding_rules, ) assert not result assert result.status == 500 def test_get_status_success(get_status_mocked_responses: dict[str, Any]) -> None: """Test call of get_status for transcoding order.""" # mocking ( flexmock(transcoding_order_model) .should_receive("get_transcoding_order") .with_args( get_status_mocked_responses["expected_result"]["transcoding_order_id"] ) .and_return(get_status_mocked_responses["transcoding_order"]) ) ( flexmock(transcoding_job_model) .should_receive("get_transcoding_jobs_by_order_id") .with_args( get_status_mocked_responses["expected_result"]["transcoding_order_id"] ) .and_return(get_status_mocked_responses["transcoding_jobs"]) ) # test function call result_response = transcoding_order.get_status( get_status_mocked_responses["expected_result"]["transcoding_order_id"] ) # checking assert result_response assert result_response.status == 200 expected_result = get_status_mocked_responses["expected_result"] assert result_response.message == expected_result @pytest.mark.parametrize( "invalid_mocked_response_key", ["transcoding_order", "transcoding_jobs"] ) def test_get_status_failure( get_status_mocked_responses: dict[str, Any], invalid_mocked_response_key: str ) -> None: """Test failure call of get_status for transcoding order.""" # data preparation expected_error = "{} response failure".format(invalid_mocked_response_key) # mocking get_status_mocked_responses[invalid_mocked_response_key] = ( response.create_fatal_response(expected_error) ) ( flexmock(transcoding_order_model) .should_receive("get_transcoding_order") .with_args( get_status_mocked_responses["expected_result"]["transcoding_order_id"] ) .and_return(get_status_mocked_responses["transcoding_order"]) ) ( flexmock(transcoding_job_model) .should_receive("get_transcoding_jobs_by_order_id") .with_args( get_status_mocked_responses["expected_result"]["transcoding_order_id"] ) .and_return(get_status_mocked_responses["transcoding_jobs"]) ) # test function call result_response = transcoding_order.get_status( get_status_mocked_responses["expected_result"]["transcoding_order_id"] ) # checking assert not result_response assert result_response.status == 500 assert result_response.errors["message"] == expected_error @pytest.mark.parametrize( "additional_job, expected_status", [ ( { "status": "completed", "transcoding_job_id": 11, "description": "", "container": "", }, transcoding.COMPLETED_STATUS, ), ( { "status": "processing", "transcoding_job_id": 11, "description": "", "container": "", }, transcoding.PROCESSING_STATUS, ), ( { "status": "error", "transcoding_job_id": 11, "description": "", "container": "", }, transcoding.ERROR_STATUS, ), ], ) def test_prepare_jobs_with_order_status( additional_job: dict[str, Any], expected_status: str, simplified_transcoding_jobs_fixture: list[dict[str, Any]], fixture_transcoding_jobs_entries: list[dict[str, Any]], ) -> None: """Test call of prepare_jobs_with_order_status.""" # data preparation additional_job.update( { "output_key": "key", "output_bucket": "bucket", "duration": 11000, "channels": 2, "codec": "pcm", "sample_rate": 44100, "bit_rate": 1411200, "bit_depth": 16, } ) test_job_entries = fixture_transcoding_jobs_entries.copy() test_job_entries.append(additional_job) expected_jobs_result = simplified_transcoding_jobs_fixture.copy() expected_jobs_result.append(additional_job) # test function call result = transcoding_order._prepare_jobs_with_order_status(test_job_entries) # checking assert result["status"] == expected_status assert result["transcoding_jobs"] == expected_jobs_result