[CI] invalid_param reliability suite and weekly http_invalid jobs (#3652)
Signed-off-by: wangyu <410167048@qq.com>
This commit is contained in:
1 parent
e277feacaf
commit
bd83ac9b4b
18 files changed
+2647
-184
No files matched your search
@@ -5,6 +5,10 @@ E2E tests for speaker_embedding API parameter.
|
||||
|
||||
Tests Base models (0.6B-Base and 1.7B-Base) which support voice cloning
|
||||
via pre-computed ECAPA-TDNN embeddings, bypassing ref_audio extraction.
|
||||
|
||||
Invalid combinations (mutually exclusive with ref_audio, empty embedding,
|
||||
wrong embedding dimensions) live in
|
||||
``tests/dfx/reliability/http_invalid/test_invalid_audio_speech.py``.
|
||||
"""
|
||||
|
||||
import os
|
||||
@@ -147,45 +151,6 @@ class TestSpeakerEmbeddingBase:
|
||||
assert len(response.content) > MIN_AUDIO_BYTES
|
||||
assert_not_silence(response.content)
|
||||
|
||||
@pytest.mark.advanced_model
|
||||
@pytest.mark.tts
|
||||
@hardware_test(res={"cuda": "L4"}, num_cards=1)
|
||||
def test_speaker_embedding_mutually_exclusive_with_ref_audio(self, omni_server) -> None:
|
||||
"""Sending both speaker_embedding and ref_audio returns 400."""
|
||||
url = f"http://{omni_server.host}:{omni_server.port}/v1/audio/speech"
|
||||
payload = {
|
||||
"model": omni_server.model,
|
||||
"input": SYN_TEXT,
|
||||
"task_type": "Base",
|
||||
"speaker_embedding": DUMMY_EMBEDDING_1024,
|
||||
"ref_audio": "https://example.com/audio.wav",
|
||||
"response_format": "wav",
|
||||
}
|
||||
with httpx.Client(timeout=30.0) as client:
|
||||
response = client.post(url, json=payload)
|
||||
|
||||
assert response.status_code == 400, f"Expected 400, got {response.status_code}: {response.text}"
|
||||
assert "mutually exclusive" in response.text
|
||||
|
||||
@pytest.mark.advanced_model
|
||||
@pytest.mark.tts
|
||||
@hardware_test(res={"cuda": "L4"}, num_cards=1)
|
||||
def test_speaker_embedding_empty_rejected(self, omni_server) -> None:
|
||||
"""Empty speaker_embedding list returns 400."""
|
||||
url = f"http://{omni_server.host}:{omni_server.port}/v1/audio/speech"
|
||||
payload = {
|
||||
"model": omni_server.model,
|
||||
"input": SYN_TEXT,
|
||||
"task_type": "Base",
|
||||
"speaker_embedding": [],
|
||||
"response_format": "wav",
|
||||
}
|
||||
with httpx.Client(timeout=30.0) as client:
|
||||
response = client.post(url, json=payload)
|
||||
|
||||
assert response.status_code == 400, f"Expected 400, got {response.status_code}: {response.text}"
|
||||
assert "non-empty" in response.text
|
||||
|
||||
|
||||
# ── 1.7B-Base model tests (2048-dim embeddings) ──
|
||||
|
||||
@@ -216,26 +181,3 @@ class TestSpeakerEmbedding1_7B:
|
||||
assert response.headers.get("content-type") == "audio/wav"
|
||||
assert verify_wav_audio(response.content), "Response is not valid WAV"
|
||||
assert len(response.content) > MIN_AUDIO_BYTES, f"Audio too small: {len(response.content)} bytes"
|
||||
|
||||
@pytest.mark.advanced_model
|
||||
@pytest.mark.tts
|
||||
@hardware_test(res={"cuda": "L4"}, num_cards=1)
|
||||
def test_1024_dim_on_1_7b_model_rejected(self, omni_server) -> None:
|
||||
"""1024-dim speaker_embedding on a 1.7B model (expects 2048) should fail gracefully."""
|
||||
url = f"http://{omni_server.host}:{omni_server.port}/v1/audio/speech"
|
||||
payload = {
|
||||
"model": omni_server.model,
|
||||
"input": SYN_TEXT,
|
||||
"task_type": "Base",
|
||||
"speaker_embedding": DUMMY_EMBEDDING_1024,
|
||||
"x_vector_only_mode": True,
|
||||
"response_format": "wav",
|
||||
"max_new_tokens": MAX_NEW_TOKENS,
|
||||
}
|
||||
with httpx.Client(timeout=120.0) as client:
|
||||
response = client.post(url, json=payload)
|
||||
|
||||
# Wrong dimensions should produce an error, not silent garbage.
|
||||
assert response.status_code == 400, f"Expected 400, got {response.status_code}: {response.text}"
|
||||
assert "speaker_embedding has 1024 dimensions" in response.text
|
||||
assert "expected 2048" in response.text
|
||||
@@ -1,5 +1,6 @@
|
||||
# tests/entrypoints/openai/test_serving_speech.py
|
||||
import asyncio
|
||||
import json
|
||||
import logging
|
||||
import os
|
||||
import struct
|
||||
@@ -564,7 +565,6 @@ class TestSpeechAPI:
|
||||
|
||||
def test_upload_voice_embedding_success(self, client):
|
||||
"""Upload a voice via speaker_embedding JSON."""
|
||||
import json
|
||||
|
||||
emb = [0.1] * 1024
|
||||
data = {
|
||||
@@ -585,7 +585,6 @@ class TestSpeechAPI:
|
||||
|
||||
def test_upload_voice_embedding_appears_in_listing(self, client):
|
||||
"""Embedding-uploaded voice appears in list with correct source."""
|
||||
import json
|
||||
|
||||
emb = [0.2] * 2048
|
||||
data = {
|
||||
@@ -606,7 +605,6 @@ class TestSpeechAPI:
|
||||
|
||||
def test_upload_voice_embedding_and_audio_mutually_exclusive(self, client):
|
||||
"""Providing both audio_sample and speaker_embedding returns 400."""
|
||||
import json
|
||||
|
||||
emb = [0.1] * 1024
|
||||
files = {"audio_sample": ("test.wav", b"fake", "audio/wav")}
|
||||
@@ -632,7 +630,6 @@ class TestSpeechAPI:
|
||||
|
||||
def test_upload_voice_embedding_nan_rejected(self, client):
|
||||
"""NaN values in speaker_embedding return 400."""
|
||||
import json
|
||||
|
||||
data = {
|
||||
"speaker_embedding": json.dumps([0.1] * 1023 + [float("nan")]),
|
||||
@@ -930,7 +927,6 @@ class TestTTSMethods:
|
||||
|
||||
def test_upload_voice_embedding_wrong_dims_rejected(self, speech_server):
|
||||
"""Embedding uploads must match the loaded Qwen3-TTS model before being stored."""
|
||||
import json
|
||||
|
||||
speech_server._tts_model_type = "qwen3_tts"
|
||||
speech_server.engine_client.model_config = SimpleNamespace(
|
||||
|
||||
Reference in new issue
Block a user