diff --git a/tests/entrypoints/openai_api/test_serving_speech.py b/tests/entrypoints/openai_api/test_serving_speech.py index 573816a0e..53edd9dc0 100644 --- a/tests/entrypoints/openai_api/test_serving_speech.py +++ b/tests/entrypoints/openai_api/test_serving_speech.py @@ -12,6 +12,7 @@ import os import struct import wave from dataclasses import FrozenInstanceError, replace +from http import HTTPStatus from inspect import Signature, signature from pathlib import Path from types import SimpleNamespace @@ -1012,6 +1013,44 @@ class TestTTSMethods: assert speed == 1.25 resolve_adapter.assert_not_called() + @pytest.mark.asyncio + async def test_create_speech_cuda_oom_returns_internal_server_error( + self, + speech_server, + mocker: MockerFixture, + ): + mocker.patch.object(speech_server, "_check_model", new=mocker.AsyncMock(return_value=None)) + mocker.patch.object( + speech_server, + "_generate_audio_bytes", + new=mocker.AsyncMock(side_effect=torch.OutOfMemoryError("CUDA out of memory")), + ) + + response = await speech_server.create_speech(OpenAICreateSpeechRequest(input="Hello")) + + assert isinstance(response, ErrorResponse) + assert response.error.code == HTTPStatus.INTERNAL_SERVER_ERROR + assert response.error.type == "InternalServerError" + + @pytest.mark.asyncio + async def test_create_speech_unexpected_failure_returns_internal_server_error( + self, + speech_server, + mocker: MockerFixture, + ): + mocker.patch.object(speech_server, "_check_model", new=mocker.AsyncMock(return_value=None)) + mocker.patch.object( + speech_server, + "_generate_audio_bytes", + new=mocker.AsyncMock(side_effect=RuntimeError("codec failed")), + ) + + response = await speech_server.create_speech(OpenAICreateSpeechRequest(input="Hello")) + + assert isinstance(response, ErrorResponse) + assert response.error.code == HTTPStatus.INTERNAL_SERVER_ERROR + assert response.error.type == "InternalServerError" + def test_is_tts_detection_no_stage(self, speech_server): """Test TTS model detection when no TTS stage exists.""" # Fixture creates server with stage_configs = [] -> _is_tts should be False @@ -3925,11 +3964,19 @@ class TestAsyncOmniSupportedTasks: assert "generate" in tasks -def test_api_server_create_speech_wraps_error_response_status(mocker: MockerFixture): +@pytest.mark.parametrize( + ("status_code", "err_type"), + [(HTTPStatus.BAD_REQUEST, "BadRequestError"), (HTTPStatus.INTERNAL_SERVER_ERROR, "InternalServerError")], +) +def test_api_server_create_speech_wraps_error_response_status( + mocker: MockerFixture, + status_code: HTTPStatus, + err_type: str, +): handler = mocker.MagicMock() handler.create_speech = mocker.AsyncMock( return_value=ErrorResponse( - error=ErrorInfo(message="bad request", type="BadRequestError", param=None, code=400), + error=ErrorInfo(message="speech failed", type=err_type, param=None, code=status_code), ) ) @@ -3938,7 +3985,12 @@ def test_api_server_create_speech_wraps_error_response_status(mocker: MockerFixt response = asyncio.run(api_server_module.create_speech(request, raw_request)) - _assert_openai_error_response(response, status_code=400, message="bad request") + _assert_openai_error_response( + response, + status_code=status_code, + message="speech failed", + err_type=err_type, + ) def _make_api_server_request(handler, *, method: str = "POST", path: str = "/v1/audio/voices") -> Request: diff --git a/vllm_omni/entrypoints/openai/serving_speech.py b/vllm_omni/entrypoints/openai/serving_speech.py index c044a67b6..40ae2f911 100644 --- a/vllm_omni/entrypoints/openai/serving_speech.py +++ b/vllm_omni/entrypoints/openai/serving_speech.py @@ -2726,8 +2726,11 @@ class OmniOpenAIServingSpeech(OpenAIServing, AudioMixin): total_ms, e, ) - logger.exception("Speech generation failed: %s", e) - return self.create_error_response(f"Speech generation failed: {e}") + return self.create_error_response( + f"Speech generation failed: {e}", + err_type="InternalServerError", + status_code=HTTPStatus.INTERNAL_SERVER_ERROR, + ) @staticmethod def _merge_batch_item(